2013-04-16 28 views
14

Làm cách nào để hợp nhất 2 khung dữ liệu tương tự nhưng có một khung có tầm quan trọng lớn hơn?Hợp nhất các khung dữ liệu và ghi đè các giá trị

Ví dụ:

Dataframe 1

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

Dataframe 2

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

hợp nhất các bằng Date with dataframe 1 chụp ưu tiên nhưng dataframe 2 chỗ trống điền

DataframeMerge

Date  Col1 Col2 Col3 
jan   2  1  10 
feb   4  2  20 
march  6  3  30 
april  8  6  40 

EDIT - GIẢI PHÁP

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 
} 

Trả lờ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) ] 

Sau đó, chỉ cần đổi tên 'merdat $ Col2.y' thành 'merdat $ Col2' và thả 'merdat $ Col2.x'.

Trả lời yêu cầu nhận xét thêm: Một cách để cập nhật chỉ các phần của vectơ là tạo một vector lôgic để lập chỉ mục và áp dụng nó bằng cách sử dụng "[" cho cả hai bên của bài tập. Một cách khác là tạo ra một vectơ logic chỉ trên LHS của một phép gán nhưng sau đó tạo một vectơ sử dụng rep() có cùng độ dài là sum(logical.vector). Mục đích là cả hai trường hợp là có cùng độ dài (và thứ tự) cho bài tập khi các mục được thay thế.

+0

câu trả lời hay, nhưng một vài ý kiến ​​khác trong mã sẽ làm cho nó rất hữu ích. – Sam

+0

Đánh giá cao câu trả lời nhưng tôi xin lỗi khi nói rằng tôi đã quên đề cập đến một phần thông tin quan trọng, ngoài cột ngày (khoá) tôi sẽ không biết các cột khác trong bảng. Một số có thể phù hợp với một số có thể không.Tôi cho rằng tôi chỉ có thể sử dụng một kết hợp giữa tên (dfrm1) và tên (dfrm2) để lấy các cột mà tôi cần để áp dụng mã của bạn? (phụ thêm x và y vào tên col của khóa học) – EvilWeebl

+0

Cảm ơn sự giúp đỡ, tôi đã lấy câu trả lời của bạn và mở rộng trên nó để trang trải khi các cột tương tự chưa được biết. Tôi đã thêm giải pháp cho câu hỏi của mình để giúp mọi người trong tương lai. – EvilWeebl

5

Hãy xem xét ví dụ sau:

> 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 

Bây giờ sử dụng mergewithin, với 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

Đây là mát mẻ, nhưng nó chỉ hoạt động nếu bạn đã biết tên cột sẽ có sẵn trong cả hai dataframes, không phải là trường hợp trong câu hỏi OP của (xem làm rõ cam kết về câu trả lời của [42-]] (https://stackoverflow.com/a/16042494/210945)). – naught101

10

Cập nhật bằng v1.9.6 của on= luận data.table (mà cho phép Adhoc tham gia:

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

Dưới đây là một giải pháp data.table Hãy chắc chắn và df2 's Date cột df1 của bạn. yếu tố với các mức mong muốn (để đặt hàng)

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

Đây là giải pháp dplyr. Tín dụng để @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 
Các vấn đề liên quan