如何使用条件更新另一个表中的值

时间:2019-08-30 09:38:05

标签: r dplyr data.table

我想用df2中的值更新表df1中的值,只更新空值或零。 我可以使用data.table或dplyr来做到这一点,但是我无法自动化所有列。

Vue.prototype.$kalendar = {};

使用dplyr至少我可以手动添加获得预期输出的列,问题是实际的数据框具有如此多的列。因此,我想跨列迭代以完成任务。

我尝试过的事情:

#data.table
df1 <- data.frame(x1=1:4, x2=c('a','b', NA, 'd'), x3=c(0,0,2,2), stringsAsFactors=FALSE)
df2 <- data.frame(x1=2:3, x2=c("zz", "qq"),x3=6:7, stringsAsFactors=FALSE)

require(data.table)
setDT(df1); setDT(df2)

df1[df2, on = .(x1), x2 := ifelse(is.na(x2) | x2 == 0 ,i.x2,x2)]

#dplyr
require(dplyr)
require(dplyr)
inner_join(df1,df2,by = c("x1" = "x1")) %>% 
  transmute(x1 = x1,
            x2 =ifelse(is.na(x2.x) | x2.x == 0,x2.y,x2.x),
            x3 =ifelse(is.na(x3.x) | x3.x == 0,x3.y,x3.x))

3 个答案:

答案 0 :(得分:2)

使用基数R,您可以创建一个函数,以将NA和0替换为另一列中的相应值

replace_na_0 <- function(x) {
   ifelse(is.na(x[[1]]) | x[[1]] == 0,x[[2]],x[[1]])
}

通过删除列后缀(.x.y)replace_na_0函数来合并和传递列组

temp_df <- merge(df1, df2, by = "x1")

cbind(temp_df[1], sapply(split.default(temp_df[-1], 
       sub("\\..*", "", names(temp_df)[-1])), replace_na_0))

#  x1 x2 x3
#1  2  b  6
#2  3 qq  2

答案 1 :(得分:1)

对于data.table,您可以使用:

for (x in setdiff(names(df1), "x1")) {
    df1[is.na(get(x)) ! get(x)==0, (x) := df2[.SD, on=.(x1), get(x)]]
}

答案 2 :(得分:0)

这是一种纯data.table方法...

熔化过程会处理您要填充的所有列,并将它们全部放在一组单独的列中(变量列和值列)。 然后使用更新联接(= fast!)填写所有0 / NA值。 最后,将所有内容重新铸造回原始形状。

library(data.table)
#set to data.table
setDT(df1)
setDT(df2)
#melt to long
melt1 <- melt(df1, id.vars = "x1" )
melt2 <- melt(df2, id.vars = "x1" )
#join all values with value NA or 0
melt1[ is.na(value) | value == 0, 
       value := melt1[ is.na( value) | value == 0,][ melt2, value := i.value, on = .(x1, variable) ]$value][]
#cast to original wide format
dcast( melt1, x1 ~ variable )

输出

#    x1 x2 x3
# 1:  1  a  0
# 2:  2  b  6
# 3:  3 qq  2
# 4:  4  d  2