2013-04-16 107 views
14

如何合并2个相似的数据帧但具有更重要的一个?合并数据帧并覆盖值

例如:

数据帧1

Date  Col1 Col2 
jan   2  1 
feb   4  2 
march  6  3 
april  8  NA 

数据帧2

Date  Col2 Col3 
jan   9  10 
feb   8  20 
march  7  30 
april  6  40 

与数据帧1采取优先次序但数据帧2填充坯

DataframeMerge

合并这些由日期
Date  Col1 Col2 Col3 
jan   2  1  10 
feb   4  2  20 
march  6  3  30 
april  8  6  40 

编辑 - 解决方案

commonNames <- names(df1)[which(colnames(df1) %in% colnames(df2))] 
commonNames <- commonNames[commonNames != "key"] 
dfmerge<- merge(df1,df2,by="key",all=T) 
for(i in commonNames){ 
    left <- paste(i, ".x", sep="") 
    right <- paste(i, ".y", sep="") 
    dfmerge[is.na(dfmerge[left]),left] <- dfmerge[is.na(dfmerge[left]),right] 
    dfmerge[right]<- NULL 
    colnames(dfmerge)[colnames(dfmerge) == left] <- i 
} 

回答

12
merdat <- merge(dfrm1,dfrm2, by="Date") # seems self-documenting 

# explanation for next line in text below. 
merdat$Col2.y[ is.na(merdat$Col2.y) ] <- merdat$Col2.x[ is.na(merdat$Col2.y) ] 

然后,只需将'merdat $ Col2.y'重命名为'merdat $ Col2'并放下'merdat $ Col2.x'即可。

回复请求更多评论:一种仅更新矢量部分的方法是为索引构建一个逻辑矢量,并使用“[”将其应用于任务的两侧。另一种方法是设计一个逻辑向量,它只在一个任务的LHS上,然后使用与sum(logical.vector)具有相同长度的rep()来创建一个向量。目标是两个实例的长度(和顺序)与被替换的项目相同。

+0

很好的答案,但在代码中的几个注释会使它非常有用。 – Sam

+0

欣赏答案,但我很遗憾地说我忘记提及一个重要的信息,除了日期(关键)列我不知道表中的其他列。有些可能会匹配一些可能不会。我想我可以使用名称(dfrm1)和名称(dfrm2)之间的匹配来获取我需要应用代码的列。 (将x和y附加到col的名字当然) – EvilWeebl

+0

感谢您的帮助,我接受了您的答案并对其进行了扩展,以涵盖相似列未知的情况。我已经将解决​​方案添加到了我的问题中,以帮助未来的任何人。 – EvilWeebl

5

考虑这个例子:

> d1 <- data.frame(x=1:4, a=2:5, b=c(3,4,5,NA)) 
> d1 
    x a b 
1 1 2 3 
2 2 3 4 
3 3 4 5 
4 4 5 NA 
> d2 <- data.frame(x=1:4, b=c(6,7,8,9), c=11:14) 
> d2 
    x b c 
1 1 6 11 
2 2 7 12 
3 3 8 13 
4 4 9 14 

现在使用mergewithin,与ifelse

> within(merge(d1, d2, by="x"), {b <- ifelse(is.na(b.x),b.y,b.x); b.x <- NULL; b.y <- NULL}) 
    x a c b 
1 1 2 11 3 
2 2 3 12 4 
3 3 4 13 5 
4 4 5 14 9 
+2

这是很酷,但如果你已经知道哪些列名称将要在这两个dataframes就不行了,是不是在OP的问题的情况下(请参阅[42-答案](https://stackoverflow.com/a/16042494/210945)上的澄清提交)。 – naught101

10

使用data.table的on=说法v1.9.6(它允许即席更新加入

setDT(df1)[df2, `:=`(Col2 = ifelse(is.na(Col2), i.Col2, Col2), 
        Col3 = i.Col3), on="Date"][] 

这里有一个data.table解决方案确保您的df1df2Date列。具有所需水平的因子(用于订购)

require(data.table) 
dt1 <- data.table(df1, key="Date") 
dt2 <- data.table(df2, key="Date") 
# Col2 refers to the Col2 of dt1 and i.col2 refers to that of dt2 
dt1[dt2, `:=`(Col3 = Col3, Col1 = Col1, 
     Col2 = ifelse(is.na(Col2), i.Col2, Col2))] 

# the result is stored in dt1 
> dt1 
#  Date Col1 Col2 Col3 
# 1: jan 2 1 10 
# 2: feb 4 2 20 
# 3: march 6 3 30 
# 4: april 8 6 40 
1

这是一个dplyr解决方案。感谢@docendo discimus

df1 <- data.frame(y = c("A", "B", "C", "D"), x1 = c(1,2,NA, 4)) 

    y x1 
1 A 1 
2 B 2 
3 C NA 
4 D 4 

df2 <- data.frame(y = c("A", "B", "C"), x1 = c(5, 6, 7)) 

    y x1 
1 A 5 
2 B 6 
3 C 7 

dplyr

left_join(df1, df2, by="y") %>% 
transmute(y, x1 = ifelse(is.na(x1.y), x1.x, x1.y)) 

    y x1 
1 A 5 
2 B 6 
3 C 7