如何加入和覆盖数据似乎是一个常见的请求,但我还没有找到适用于整个数据集的优雅解决方案。
(注意:为了简化数据,我将仅使用1和NA作为值和一小部分列,但实际上我有数百个具有不同值的列。)
我有一个数据表(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]
我还有另一个数据表(d2),它包含额外的列以及d1中现有列中缺少的数据点。
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 ]
我想基本上加入+用d2中的所有数据覆盖d1,确保按名称匹配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并仅覆盖NAs以获取:
> 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 :(得分:2)
我认为最简单的形式是:
md1 = melt(d2, id="id")
md2 = melt(d2, id="id")
然后你可以叠加它们并获取最新值:
res1 = unique(rbind(md1, md2), by=c("id", "variable"), fromLast=TRUE)
如果您只想更新[
d3
]中的NA值,我也想知道如何做到这一点,也就是说,确保不会覆盖现有的非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 :(得分:1)
来自评论的@ Frank解决方案。 (注意:首先需要将d1和d2定义为data.table)。
library(data.table)
cols = setdiff(intersect(names(d1), names(d2)), "id")
d1[d2, on=.(id), (cols) := mget(paste0("i.", cols))]
正如他所指出的,我在下面提供的原始解决方案一般来说是一个坏主意。如果id出现多次或以不同的顺序出现,则会出错。
d1 [d1 $ id%in%d2 $ id,names(d2):= d2]
答案 2 :(得分:0)
library("dplyr")
d12 <- anti_join(d1, d2, by = "id") %>%
bind_rows(d2)
此解决方案从d1
中获取不的d2
行,然后将d2
行添加到其中。
这对“附加方案”不起作用,后者看起来要麻烦得多,也许应该是一个单独的问题。