2013-04-16 105 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