2017-10-15 53 views
2

如何連接和覆蓋數據似乎是一個常見請求,但我還沒有找到適用於整個數據集的優雅解決方案。 (注意:爲了簡化數據,我將只使用1和NAs作爲值和列的一小部分,但實際上我有幾百個具有不同值的列)。使用另一個表中的數據連接並覆蓋一個表中的數據

我有一個數據表(d1)在某些列和行中有NA值。

library(data.table) 
d1 = fread(
"r id v1 v2 v3 
1 A 1 1 1 
2 B 1 1 1 
3 C 1 NA NA 
4 D 1 1 NA 
5 E 1 NA 1")[, r := NULL] 

而且我有一個包含額外的列以及從D1現有列丟失的數據點的另一個數據表(D2)。

d2 = fread(
"r id v2 v3 v4 v5 
1 C 1 1 1 1 
2 D 1 1 1 1 
3 E 1 1 1 1")[, r := NULL ] 

我想基本上加盟+覆蓋D1與D2中的所有數據,確保課程的名字,以匹配ID和列的行,如下圖所示。

> d12 
    id v1 v2 v3 v4 v5 
1 A 1 1 1 NA NA 
2 B 1 1 1 NA NA 
3 C 1 1 1 1 1 
4 D 1 1 1 1 1 
5 E 1 1 1 1 1 

附加方案:我也想知道如何可以做到這一點,如果你只想在D1更新NA值,也就是確保現有的非NA值不會被覆蓋。 (爲了使這更容易可視化,我將包含1和0的新表)。

例如,如果我們已經D3

d3 = fread(
"r id v1 v2 v3 
1 A 1 1 1 
2 B 1 1 1 
3 C 1 0 NA 
4 D 1 1 0 
5 E 1 NA 1")[, r := NULL ] 

我們想加入d2和只覆蓋港定居人士獲得:

> d32 
    id v1 v2 v3 v4 v5 
1 A 1 1 1 NA NA 
2 B 1 1 1 NA NA 
3 C 1 0 1 1 1 
4 D 1 1 0 1 1 
5 E 1 1 1 1 1 

僅供參考,下面是一些其他職位解決這個問題,但只一個或兩個欄目。我正在尋找的解決方案應該允許一個表中的數據被許多(如果不是全部)另一個表中的列覆蓋。

Merge data frames and overwrite values

Merge two data frame and replace the NA value in R

一個data.table爲基礎的解決方案是首選,但其他人的歡迎。

回答

0
library("dplyr") 

d12 <- anti_join(d1, d2, by = "id") %>% 
     bind_rows(d2) 

該解決方案從d1取行時,d2,然後添加到他們的d2行。

這不適用於'其他場景',這看起來更加混亂以解決,也許應該是一個單獨的問題。

+1

它是'by =「id」'? – Suren

+1

由於行綁定導致數據不完整,因此不會執行此操作。 – AlexR

1

這裏是@弗蘭克的解決方案從評論。 (注意:首先需要將d1和d2定義爲data.table)。

library(data.table) 
cols = setdiff(intersect(names(d1), names(d2)), "id") 
d1[d2, on=.(id), (cols) := mget(paste0("i.", cols))] 

正如他所指出的,我下面提供的原始解決方案是一個壞主意一般來說。如果ids出現多次或以不同的順序,它會做錯誤的事情。

D1 [以%D2的$ id D1的$ id%,名稱(D2):= D2]

+1

這是一個糟糕的主意。如果ids出現多次或以不同的順序,它會做錯誤的事情。我認爲:'cols = setdiff(intersect(names(d1),names(d2)),「id」); d1 [d2,on =。(id),(cols):= mget(paste0(「i。」,cols))]'。我發佈的評論,因爲它基本上是與你的答案相同的想法,你可以編輯它,如果你想。 – Frank

+0

Frank,我歡迎你(或任何其他人)在附加場景中採取措施,除非有可能取代非NA值的NAs,否則要覆蓋數據。我鏈接的帖子中有一些data.table解決方案,我希望可以應用到多個列(即所有正在更新的列)。 – AlexR

+0

我不確定我瞭解你描述的情況。我猜,一個不會覆蓋NAs的粗糙方法會使用'replace'或'ifelse'。您可以發佈一個新問題。 – Frank

2

我認爲這是最簡單的去長型:

md1 = melt(d2, id="id") 
md2 = melt(d2, id="id") 

然後你就可以堆疊起來,並採取最新值:

res1 = unique(rbind(md1, md2), by=c("id", "variable"), fromLast=TRUE) 

我也想知道如何可以做到這一點,如果你只是想更新的NA值[ d3],即確保現有的非NA值不被覆蓋。

您可以從更新表,md2排除行,如果他們出現在md3

md3 = melt(d3, id="id") 

res3 = unique(rbind(md3, md2[!md3, on=.(id, variable)]), 
    by=c("id", "variable"), fromLast=TRUE) 

dcast可以使用,如果有必要回到寬幅,例如,dcast(res3, id ~ ...)

+1

有趣的方法,它運作良好。然而,熔解會將所有數據強制轉換爲一種類型,所以如果您同時擁有字符和整數數據,將會產生問題(我承認我的示例過於簡化)。我會在每個步驟的末尾添加decast,因爲這是最終數據的外觀(即寬格式是原始格式)。 – AlexR

相關問題