【问题标题】:Replace missing values (NA) in one data set with values from another where columns match将一个数据集中的缺失值 (NA) 替换为列匹配的另一个数据集中的值
【发布时间】:2015-12-14 19:48:37
【问题描述】:

我有一个包含 3 列“x”、“y”和“z”的数据框 (datadf)。缺少几个“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

我希望将“datadf”中“x”中的NA 替换为“imputeddf”中的值,其中“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的最佳方式是什么?

【问题讨论】:

  • 也许是示例输入和输出格式正确的示例?
  • 发布示例应该产生的所需数据帧。
  • k 添加了我想要的结果,授予 col Z 超过 2 个选项
  • 数据 df 有多个 y 和 z 组合实例,我只是想从我的推算数据框中切换出值的 NA 值,这似乎只是将数据框合并为一个。跨度>

标签: r plyr


【解决方案1】:

我会这样做:

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

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

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

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


来自@Jakob 的评论:

这是否适用于多个 x 变量?如果我想用几列填充整个数据集?

您可以枚举所需的列:

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

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

【讨论】:

  • 如果data.table允许DF1[DF2, x[is.na(x)] := i.x, on=c("y","z")]就好了
  • dt1[is.na(x), x := dt2[.SD, x, on=c("y", "z")]]
  • @Frank 这是否适用于多个 x 变量?如果我想用几列填充整个数据集?
  • @Jakob 我在上面以一种方式进行了编辑,希望对您有所帮助。如果您正在寻求一些不那么手动的帮助(而不是为每列写一行),那么可能值得制作一个可重复的示例并发布一个新问题
【解决方案2】:

dplyr 解决方案,概念上与上述答案相同。要仅提取与 datadf 中的 NA 对应的 imputeddf 行,请使用 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

【讨论】:

    【解决方案3】:

    这里有一个基于 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
    

    【讨论】:

    • 你有序列 2:3 我可以用 c(df$y,df$z) 替换它吗?
    • 当 df1 对于 z==1 & y==1 有多个 x 值(包括 NA)时会怎样
    • 收到此错误:[&lt;-.data.frame(*tmp*, is.na(dataimp$steps), "steps", value = c(NA, : 替换有 17568 行,数据有 2304 行) 中的错误
    • steps 是我的 x,dataimp 是我的 df1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 2021-07-29
    • 1970-01-01
    • 2021-11-27
    • 2020-09-04
    • 1970-01-01
    相关资源
    最近更新 更多