如何更新连接中的两个 data.tables

mni*_*ist 6 merge r data.table

假设我想跟踪一个 data.table 中的哪些行已合并到另一个 data.table 中。有没有办法立即/合并时执行此操作?请参阅下面的示例以及我通常的做法。然而,这似乎效率很低。

例子

library(data.table)

# initial data
DT = data.table(x = c(1,1,1,2,2,1,1,2,2), 
                y = c(1,3,6))

# data to merge
DTx <- data.table(x = 1:3,
                  y = 1,
                  k = "X")

# regular update join
copy(DT)[DTx,
         on = .(x, y),
         k := i.k][]
#>    x y    k
#> 1: 1 1    X
#> 2: 1 3 <NA>
#> 3: 1 6 <NA>
#> 4: 2 1    X
#> 5: 2 3 <NA>
#> 6: 1 6 <NA>
#> 7: 1 1    X
#> 8: 2 3 <NA>
#> 9: 2 6 <NA>

# DTx remains the same
DTx
#>    x y k
#> 1: 1 1 X
#> 2: 2 1 X
#> 3: 3 1 X
Run Code Online (Sandbox Code Playgroud)

我通常做的事:

# set an Id variable
DTx[, Id := .I]

# assign the Id in merge
DT[DTx,
   on = .(x, y),
   `:=`(k = i.k,
        matched_id = i.Id)][]
#>    x y    k matched_id
#> 1: 1 1    X          1
#> 2: 1 3 <NA>         NA
#> 3: 1 6 <NA>         NA
#> 4: 2 1    X          2
#> 5: 2 3 <NA>         NA
#> 6: 1 6 <NA>         NA
#> 7: 1 1    X          1
#> 8: 2 3 <NA>         NA
#> 9: 2 6 <NA>         NA

# use matched_id to find merged rows
DTx[, matched := fifelse(Id %in% DT$matched_id, TRUE, FALSE)]
DTx
#>    x y k Id matched
#> 1: 1 1 X  1    TRUE
#> 2: 2 1 X  2    TRUE
#> 3: 3 1 X  3   FALSE
Run Code Online (Sandbox Code Playgroud)

Fra*_*ank 1

以下是简的评论:

这将为您提供匹配行的索引,但您必须再次调用 merge 来执行实际合并,除非您手动使用提供的索引来匹配/更新这些表。

您可以提取索引:

merge_metaDT = DT[DTx, on=.(x, y), .(irow = .GRP, xrow = .I), by=.EACHI]

   x y irow xrow
1: 1 1    1    1
2: 1 1    1    7
3: 2 1    2    4
4: 3 1    3    0
Run Code Online (Sandbox Code Playgroud)

然后使用索引对每个表应用编辑,而不是再次合并或匹配:

rowDT = merge_metaDT[xrow != 0L]
DT[rowDT$xrow, k := DTx[rowDT$irow, k]]
DTx[, matched := FALSE][rowDT$irow, matched := TRUE]
Run Code Online (Sandbox Code Playgroud)

怎么运行的

  • 连接时,x[i]符号.I索引行x
  • 在 join 中分组时by=.EACHI.GRP为每个组建立索引,这意味着i这里的每一行
  • .I我们删除编码为零的不匹配值

关于最后一点,我们可能期望 NA 而不是 0 返回的零DT[DTx, on=.(x, y), which=TRUE]。我不确定为什么这些不同。


假设我想跟踪一个 data.table 中的哪些行已合并到另一个 data.table 中。有没有办法立即/合并时执行此操作?[...] 似乎效率很低。

我预计这比多次合并或%in%合并成本足够高时更有效。

它仍然需要多个步骤。我怀疑有什么办法可以解决这个问题,因为很难为更新提供易于遵循的逻辑和语法。

基础 R 中的更新逻辑已经很复杂,允许对单个索引进行多次编辑:

> x = c(1, 2, 3)
> x[c(1, 1)] = c(4, 5)
> x
[1] 5 2 3
Run Code Online (Sandbox Code Playgroud)

还有一个问题是如何同时匹配和编辑多个索引:

> x = c(1, 1, 3)
> x[match(c(1, 3), x)] = c(4, 5)
> x
[1] 4 1 5
Run Code Online (Sandbox Code Playgroud)

在 data.table 更新中,后一个问题是用 处理的mult=。在更新两个表的用例中,这些问题会变得更加复杂。