使用相同的列填充另一个数据框中的缺失值

时间:2018-02-14 16:43:18

标签: r

我搜索了各种加入问题,似乎没有人回答这个问题。我有两个数据帧,每个数据帧都有一个ID列和几个信息列。

df1 <- data.frame(id = c(1:100), color = c(rep("blue", 25), rep("red", 25), 
                  rep(NA, 25)), phase = c(rep("liquid", 50), rep("gas", 50)),
                  rand.col = rnorm(100))

df2 <- data.frame(id = c(51:100), color = rep("green", 50), phase = rep("gas", 50))

如您所见,df1缺少df2中存在的某些信息,而df2只是所有ID的子集,但它们都有一些类似的列。有没有办法根据DF2的匹配ID来填充df1中的缺失值?

我找到了一个推荐使用merge的similar question,但是当我尝试使用它时,它删除了两个数据帧中都不存在的所有id。此外,它需要手动删除重复列,在我的真实数据集中,会有大量这些,这样做很麻烦。甚至忽略了这一点,

两种推荐的解决方案:

df1 <- setNames(merge(df1, df2)[-2], names(df1))

df1[is.na(df1$color), "color"] <- df2[match(df1$id, df2$id), "color"][which(is.na(df1$color))]

对我不起作用,引发各种错误。

我想到的另一种解决方案是使用rbind然后删除不完整的案例。问题是在我的真实数据集中,虽然有共享列,但也有非共享列,所以我必须创建仅共享列的中间对象rbind,然后删除不完整的案例,然后{{ 1}}用原始对象重新获得删除的列。这似乎是不必要的回合。

在此示例中,它看起来像

join

并且,如果两个数据帧之间有任何完全重复的行,我需要添加

df2 = rbind(df1[,colnames(df2)], df2)
df2 = df2[complete.cases(df2),]
df2 = merge(df1[,c("id", "rand.col")], df2, by = "id")

这个解决方案可行,但它很麻烦,随着匹配的列数增加,情况会变得更糟。有更好的解决方案吗?

-edit-修复了Sathish指出的示例数据中的问题

-edit2-扩展示例数据

df2 = unique(df2)

这些数据框表示存在许多具有不完整数据的列和具有所有缺失数据的第二个数据帧的情况。理想情况下,我们不需要使用df1 = data.frame(id = c(1:100), wq2 = rnorm(50), wq3 = rnorm(50), wq4 = rnorm(50), wq5 = rnorm(50)) df2 = data.frame(id = c(51:100), wq2 = rnorm(50), wq3 = rnorm(50), wq4 = rnorm(50), wq5 = rnorm(50)) 等单独列出每个列。

1 个答案:

答案 0 :(得分:2)

如果您只想通过id列加入,可以在下面代码的phase子句中删除on

此外,您在问题中的数据也存在差异,这些差异已在此答案中发布的数据中得到纠正。

library('data.table')
setDT(df1)  # make data table by reference
setDT(df2)  # make data table by reference
df1[ i = df2, color := i.color, on = .(id, phase)] # join df1 with df2 by id and phase values, and replace color values of df2 with color values of df1

tail(df1)
#     id color phase   rand.col
# 1:  95 green   gas  1.5868335
# 2:  96 green   gas  0.5584864
# 3:  97 green   gas -1.2765922
# 4:  98 green   gas -0.5732654
# 5:  99 green   gas -1.2246126
# 6: 100 green   gas -0.4734006

单行:

setDT(df1)[df2, color := i.color, on = .(id, phase)]

数据:

set.seed(1L)
df1 <- data.frame(id = c(1:100), color = c(rep("blue", 25), rep("red", 25), 
                                           rep(NA, 50)), phase = c(rep("liquid", 50), rep("gas", 50)),
                  rand.col = rnorm(100))

df2 <- data.frame(id = c(51:100), color = rep("green", 50), phase = rep("gas", 50))

编辑:根据问题中发布的新数据

数据:

set.seed(1L)
df1 = data.frame(id = c(1:100),  wq2 = rnorm(50), wq3 = rnorm(50), wq4 = rnorm(50), 
                 wq5 = rnorm(50))
set.seed(2423L)
df2 = data.frame(id = c(51:100), wq2 = rnorm(50), wq3 = rnorm(50), wq4 = rnorm(50), 
                 wq5 = rnorm(50))

代码:

library('data.table')
setDT(df1)[ id == 52, ]
#    id       wq2        wq3        wq4         wq5
# 1: 52 0.1836433 -0.6120264 0.04211587 -0.01855983

setDT(df2)[ id == 52, ]
#    id       wq2       wq3        wq4       wq5
# 1: 52 0.3917297 -1.007601 -0.6820783 0.3153687

df1[df2, `:=` ( wq2 = i.wq2,
                wq3 = i.wq3,
                wq4 = i.wq4,
                wq5 = i.wq5), on = .(id)]

setDT(df1)[ id == 52, ]
#    id       wq2       wq3        wq4       wq5
# 1: 52 0.3917297 -1.007601 -0.6820783 0.3153687