关于缺失数据:r 非 NA 列值之间的差异

r difference between non-NA column values

我需要连续计算非 NA 值之间的差异。例如,如果只有a、c和e点有值,而b和d中的值为NA,我需要计算c和a、e和c之间的差值,并留下b和a之间的差值和d 和 c 空白。 d1 是 b 中的非 NA 值与左侧最近的非 NA 值之间的差(必须是 a 中的非 NA 值)。 d2 是 c 中的非 NA 值与左侧最近的非 NA 值之间的差。 d3 是 d 中的非 NA 值与左侧最近的非 NA 值之间的差。 d4 是 e 中的非 NA 值与左侧最近的非 NA 值之间的差。

我认为我缺少一些可在这种情况下使用的 R 函数。我尝试编写一些 ifelse 条件来说明前面的数据点为 NA,结果证明这是一个很长的 ifelse 语句。
df$d1<-ifelse(!is.na(df$a and !is.na(df$b), df$b-df$a)
但是我离 a 越远,ifelse 语句就越复杂。
我也试过写
df$d1<-(!is.na(df$b))-(!is.na(df$a))
结果不是差异,而是第一个数据点是否为 NA (我在 d1 列中得到 0、1、-1)。

这是我原始数据库的结构:

1
2
3
4
5
6
```a<-c(10, 20, NA, 40, 50, 60)
b<-c(5, NA, 6, 7, NA, 8)
c<-c(NA, 4, 5, NA, 7, 8)
d<-c(NA, 9, 8, 7, 6, 5)
e<-c(3, 4, NA, 5, 6, 7)
df<-data.frame(a, b, c, d, e)```

这就是我需要的结果:

1
2
3
4
5
```d1<-c('-5','' ,'' , '-33','', '-52')
d2<-c('', '-16', '-1', '', '-43', '0')
d3<-c('', '5', '3', '0', '-1', '-3')
d4<-c('-2', '-5', '', '-2', '0', '2')
df1<-data.frame(d1, d2, d3, d4)```

这是一个选项。我们使用 pmap 遍历行(或使用 base R 中的 applyMARGIN = 1),获取相邻非 NA 元素 (\\'i1\\') 的 differnce,绑定行 (pmap_dfr), select 以正确顺序排列的列名和 rename

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
library(dplyr)
library(stringr)
library(purrr)
pmap_dfr(df,  ~ {
       x <- c(...)
      i1 <- !is.na(x)
       diff(x[i1]) %>%
    as.list}) %>%      
  select(sort(names(.))) %>%
  rename_all(~ str_c('d', seq_along(.)))
# A tibble: 6 x 4
#     d1    d2    d3    d4
#  <dbl> <dbl> <dbl> <dbl>
#1    -5    NA    NA    -2
#2    NA   -16     5    -5
#3    NA    -1     3    NA
#4   -33    NA     0    -2
#5    NA   -43    -1     0
#6   -52     0    -3     2

注意:这里,默认情况下,缺少的元素将用 NA 填充。最好不要使用空白字符串 (""),因为它会将列类型从 numeric 更改为 character

如果我们只有 NA 行,找到

1
2
3
4
5
6
7
8
9
pmap_dfr(df,  ~ {
     x <- c(...)
    i1 <- !is.na(x)
    if(any(i1)) {
     diff(x[i1]) %>%
     as.list
    } else set_names(rep(list(NA_real_), length(x)-1), names(x)[-1])}) %>%      
  select(sort(names(.))) %>%
  rename_all(~ str_c('d', seq_along(.)))