用列匹配的另一个数据集中的值替换一个数据集中的缺失值 (NA)

Replace missing values (NA) in one data set with values from another where columns match

我有一个包含 3 列的数据框 (datadf),'x'、'y 和 z。缺少几个 'x' 值 (NA)。 'y' 和 'z' 是非测量变量。

x    y z
153  a 1
163  b 1
NA   d 1
123  a 2 
145  e 2
NA   c 2 
NA   b 1
199  a 2

我有另一个具有相同三列的数据框 (imputeddf):

 x  y z
123 a 1
145 a 2
124 b 1
168 b 2
123 c 1
176 c 2
184 d 1
101 d 2

我希望用 'imputeddf' 中的值替换 'x' in 'datadf' 中的 NA,其中 'y' 和 'z' 两者匹配数据集('y' 和 'z' 的每个组合都有自己的值 'x' 需要填写)。

想要的结果:

x    y z
153  a 1
163  b 1
184  d 1
123  a 2 
145  e 2
176  c 2 
124  b 1
199  a 2

我正在尝试这样的事情:

finaldf <- datadf
finaldf$x <- if(datadf[!is.na(datadf$x)]){ddply(datadf, x=imputeddf$x[datadf$y == imputeddf$y & datadf$z == imputeddf$z])}else{datadf$x}

但它不起作用。

使用我的估算值 df 填写 NA 的最佳方法是什么?

我会这样做:

library(data.table)
setDT(DF1); setDT(DF2)

DF1[DF2, x := ifelse(is.na(x), i.x, x), on=c("y","z")]

这给出了

     x y z
1: 153 a 1
2: 163 b 1
3: 184 d 1
4: 123 a 2
5: 145 e 2
6: 176 c 2
7: 124 b 1
8: 199 a 2

评论。这种方法不是很好,因为它合并了 DF1whole,而我们只需要合并 is.na(x) 的子集。在这里,改进看起来像(感谢@Arun):

DF1[is.na(x), x := DF2[.SD, x, on=c("y", "z")]]

这种方式类似于@RHertel 的回答。


来自@Jakob 的评论:

does this work for more than one x variable? If I want to fill up entire datasets with several columns?

您可以枚举所需的列:

DF1[DF2, `:=`(
  x = ifelse(is.na(x), i.x, x),
  w = ifelse(is.na(w), i.w, w)
), on=c("y","z")]

表达式可以使用 lapplysubstitute 构造,可能,但是如果列集是固定的,那么像上面那样写出来可能是最干净的。

这是一个以 R 为基数的替代方案:

df1[is.na(df1$x),"x"] <- merge(df2,df1[is.na(df1$x),][,c("y","z")])$x
> df1
#    x y z
#1 153 a 1
#2 163 b 1
#3 124 b 1
#4 123 a 2
#5 145 e 2
#6 176 c 2
#7 184 d 1
#8 199 a 2

一个dplyr解决方案,在概念上与上述答案相同。要仅提取 imputeddf 中对应于 datadf 中的 NA 的行,请使用 semi_join。然后,使用另一个连接匹配回 datadf。 (不幸的是,这一步不是很干净。)

library(dplyr)
replacement_rows <- imputeddf %>%
  semi_join(datadf %>% filter(is.na(x)), by = c("y", "z"))
datadf <- datadf %>%
  left_join(replacement_rows, by = c("y", "z")) %>%
  mutate(x = if_else(is.na(x.x), x.y, x.x)) %>%
  select(x, y, z)

这就是你想要的:

> datadf
# A tibble: 8 x 3
      x y         z
  <dbl> <chr> <dbl>
1   153 a         1
2   163 b         1
3   184 d         1
4   123 a         2
5   145 e         2
6   176 c         2
7   124 b         1
8   199 a         2