【问题标题】:How to update both data.tables in a join如何更新连接中的两个 data.tables
【发布时间】:2022-01-09 03:52:36
【问题描述】:

假设我想跟踪一个 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

我通常做什么:

# 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

【问题讨论】:

  • 我还没有看到任何支持就地修改 both 帧的合并/加入机制,即使使用 data.table 的引用语义也是如此。我认为您对matched := ... 的使用是我目前能想到的最好的。
  • (坦率地说,这里不需要fifelse ...只需matched := Id %in% DT$matched_id就足够了。)
  • 好点!并感谢您的想法
  • 感谢提示。但是,它只返回DT 中的行,因此我仍然需要加入两次,这通常比我的常规替代方法效率低
  • 要在双方都匹配,您需要访问内部函数。截至目前,我不确定是否有一个你可以很好地获得它。查看 merglist PR github.com/Rdatatable/data.table/pull/4370 查看 dtmerge 函数。

标签: r merge data.table


【解决方案1】:

根据 Jan 的评论:

这将为您提供匹配行的索引,但您必须再次调用 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

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

rowDT = merge_metaDT[xrow != 0L]
DT[rowDT$xrow, k := DTx[rowDT$irow, k]]
DTx[, matched := FALSE][rowDT$irow, matched := TRUE]

它是如何工作的

  • 在加入x[i] 时,符号.I 索引x 的行
  • 在与by=.EACHI 的联接中进行分组时,.GRP 为每个组编制索引,这意味着此处为i 的每一行
  • 我们删除了.I 的不匹配值,这些值被编码为零

在最后一点上,我们可能期望 NA 而不是零,正如 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

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

> x = c(1, 1, 3)
> x[match(c(1, 3), x)] = c(4, 5)
> x
[1] 4 1 5

在data.table更新中,后一个问题is handled with mult=。在 update-two-tables 用例中,这些问题会变得更加复杂。

【讨论】:

  • 感谢您的回答,很抱歉只是点赞,而不是发表评论。这种方法非常有用!这不是我正在寻找的那种解决方案,而是一种(更有效的)解决方法。因此不会接受它,因为将来可能会有一个“真正的”解决方案。
猜你喜欢
  • 2014-05-07
  • 2020-09-24
  • 1970-01-01
  • 2016-03-24
  • 2012-12-17
  • 1970-01-01
  • 2011-12-16
  • 2019-08-07
  • 2019-12-24
相关资源
最近更新 更多