You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在join操作过程中同时更新两个data.table对象

问题描述

我想要追踪一个data.table中的哪些行被合并到了另一张data.table中,是否可以在合并的同时一次性完成该操作?以下是我的示例以及我目前常用的实现方式,但该方式效率偏低。

示例

library(data.table)

# 初始数据
DT = data.table(x = c(1,1,1,2,2,1,1,2,2), 
                y = c(1,3,6))

# 待合并数据
DTx <- data.table(x = 1:3,
                  y = 1,
                  k = "X")

# 常规更新连接
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未发生变化
DTx
#>    x y k
#> 1: 1 1 X
#> 2: 2 1 X
#> 3: 3 1 X

目前常用的实现方式

# 新增Id变量
DTx[, Id := .I]

# 合并时赋值Id
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

# 用matched_id筛选被合并的行
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

解决方案

可以通过data.table的.EACHI分组特性一次性完成操作,无需额外创建Id列、也无需后续做低效的向量匹配,性能提升非常明显,尤其适合大数据量场景。

实现代码

方案1:无需保留DT中的匹配Id,仅标记DTx的匹配状态

# 初始化原始数据
DT = data.table(x = c(1,1,1,2,2,1,1,2,2), y = c(1,3,6))
DTx <- data.table(x = 1:3, y = 1, k = "X")

# 一步完成DT更新 + DTx匹配标记
DT[DTx, on = .(x,y),
   # 给DT更新k字段
   `:=`(k = i.k),
   # 按DTx的每一行匹配结果分组
   by = .EACHI,
   # 给DTx的对应匹配行打标记
   DTx[.BY, matched := TRUE]
][]

# 查看DTx结果,默认未匹配的行matched为NA,可按需赋值为FALSE
DTx[is.na(matched), matched := FALSE][]
#>    x y k matched
#> 1: 1 1 X    TRUE
#> 2: 2 1 X    TRUE
#> 3: 3 1 X   FALSE

方案2:需要保留DT中的匹配Id

DT = data.table(x = c(1,1,1,2,2,1,1,2,2), y = c(1,3,6))
DTx <- data.table(x = 1:3, y = 1, k = "X")[, Id := .I]

# 一次连接完成所有操作
DT[DTx, on = .(x,y),
   `:=`(k = i.k, matched_id = i.Id),
   by = .EACHI,
   DTx[.BY, matched := TRUE]
][]

DTx[is.na(matched), matched := FALSE][]
#>    x y k Id matched
#> 1: 1 1 X  1    TRUE
#> 2: 2 1 X  2    TRUE
#> 3: 3 1 X  3   FALSE

原理说明

.EACHI会按右表(此处为DTx)的每一行匹配结果分组,.BY存储了当前分组的连接键值,直接用该键值对DTx做更新操作,全程使用data.table的二分查找索引,避免了原方案中%in%操作的全量向量扫描,时间复杂度更低。


内容的提问来源于stack exchange,提问作者mnist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 09:54:02