基于多个非唯一列合并替换

时间:2017-04-04 02:16:34

标签: r merge data.table dplyr

我有两个数据框。第一个包含图像的原始状态,其中所有数据都可用于从头开始重建图像(整个坐标集及其颜色值)。

然后我有第二个数据框。这个较小,仅包含有关更新状态和原始状态之间的差异(所做的更改)的数据。有点像关键帧的视频编码。

很遗憾,我没有唯一的ID列来帮助我匹配它们。我有一个x列,我有一个y列,结合起来,可以组成一个唯一的id。

我的问题是:合并这两个数据集的优雅方法是什么,将原始数据框中的值替换为"差异"中的值。 x y坐标匹配的数据框。

以下是一些示例数据:

original <- data.frame(x = 1:10, y = 23:32, value = 120:129)

    x  y value
1   1 23   120
2   2 24   121
3   3 25   122
4   4 26   123
5   5 27   124
6   6 28   125
7   7 29   126
8   8 30   127
9   9 31   128
10 10 32   129

具有更新差异的数据框:

update <- data.frame(x = c(1:4, 8), y = c(2, 24, 17, 23, 30), value = 50:54)

  x  y value
1 1  2    50
2 2 24    51
3 3 17    52
4 4 23    53
5 8 30    54

所需的最终输出应包含原始数据框中的所有行。但是,原始中x和y坐标两者更新中相应坐标相匹配的行应具有替换为更新数据框中的值。这是所需的输出:

original_updated <- data.frame(x = 1:10, y = 23:32, 
                               value = c(120, 51, 122:126, 54, 128:129))

    x  y value
1   1 23   120
2   2 24    51
3   3 25   122
4   4 26   123
5   5 27   124
6   6 28   125
7   7 29   126
8   8 30    54
9   9 31   128
10 10 32   129

我试图想出一个带索引的矢量化解决方案已有一段时间了,但我无法弄明白。如果它只是一个具有唯一ID的列,我通常会使用%in%。但这两列并不是唯一的。

一种解决方案是将它们视为字符串或元组,并将它们组合为一列作为坐标对,然后使用%in%。

但我很好奇是否有任何解决此问题的方法涉及使用布尔向量进行索引。有什么建议吗?

2 个答案:

答案 0 :(得分:3)

首先合并的方式保证原始的所有值都存在:

merged = merge(original, update, by = c("x","y"), all.x = TRUE)

然后使用dplyr尽可能选择update的值,否则选择original的值:

library(dplyr)
middle = mutate(merged, value = ifelse(is.na(value.y), value.x, value.y))
final = select(middle, x, y, value)

答案 1 :(得分:1)

匹配函数用于生成索引。需要一个nomatch参数来阻止data.frame.[<-左侧的NA。我不认为它像合并后跟替换一样透明,但我猜它会更快:

original[  match(update$x, original$x)[
                                       match(update$x, original$x, nomatch=0) == 
                                       match(update$y, original$y,nomatch=0)]   ,
          "value"] <- 
  update[ which( match(update$x, original$x) == match(update$y, original$y)), 
           "value"]

你可以看到差异:

> match(update$x, original$x)[
            match(update$x, original$x) == 
                match(update$y, original$y) ]
[1] NA  2 NA  8
> match(update$x, original$x)[
            match(update$x, original$x, nomatch=0) == 
                match(update$y, original$y,nomatch=0)]
[1] 2 8

&#34;内饰&#34;匹配函数正在返回:

> match(update$y, original$y)
[1] NA  2 NA  1  8
> match(update$x, original$x)
[1] 1 2 3 4 8