我想用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))
答案 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