2017-10-15 45 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

相关问题