使用另一个表中的数据连接并覆盖一个表中的数据
如何连接和覆盖数据似乎是一个常见请求,但我还没有找到适用于整个数据集的优雅解决方案。 (注意:为了简化数据,我将只使用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为基础的解决方案是首选,但其他人的欢迎。
library("dplyr")
d12 <- anti_join(d1, d2, by = "id") %>%
bind_rows(d2)
该解决方案从d1
取行时,不在d2
,然后添加到他们的d2
行。
这不适用于'其他场景',这看起来更加混乱以解决,也许应该是一个单独的问题。
这里是@弗兰克的解决方案从评论。 (注意:首先需要将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]
这是一个糟糕的主意。如果ids出现多次或以不同的顺序,它会做错误的事情。我认为:'cols = setdiff(intersect(names(d1),names(d2)),“id”); d1 [d2,on =。(id),(cols):= mget(paste0(“i。”,cols))]'。我发布的评论,因为它基本上是与你的答案相同的想法,你可以编辑它,如果你想。 – Frank
Frank,我欢迎你(或任何其他人)在附加场景中采取措施,除非有可能取代非NA值的NAs,否则要覆盖数据。我链接的帖子中有一些data.table解决方案,我希望可以应用到多个列(即所有正在更新的列)。 – AlexR
我不确定我了解你描述的情况。我猜,一个不会覆盖NAs的粗糙方法会使用'replace'或'ifelse'。您可以发布一个新问题。 – Frank
我认为这是最简单的去长型:
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 ~ ...)
。
有趣的方法,它运作良好。然而,熔解会将所有数据强制转换为一种类型,所以如果您同时拥有字符和整数数据,将会产生问题(我承认我的示例过于简化)。我会在每个步骤的末尾添加decast,因为这是最终数据的外观(即宽格式是原始格式)。 – AlexR
它是'by =“id”'? – Suren
由于行绑定导致数据不完整,因此不会执行此操作。 – AlexR