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

如何在R中按分组并基于最近值合并两个data.table?

按分组匹配最近值合并data.table

问题背景

我有如下数据:

library(data.table)

bioargo <- data.table(
  grp = c("a", "a", "b", "b"),
  val = 1:4,
  x = c(2.1, 2.2, 1.9, 3)
)

hplc <- data.table(
  x = c(2, 2.3),
  z = c("foo", "bar")
)

需要将两个data.table按grp分组,对hplc的每一行,获取bioargo中每个分组里x值最接近的记录,预期输出如下:

data.table(
  x = c(2, 2.3),
  z = c("foo", "bar"),
  val = c(1, 3, 2, 2)
)
#>      x   z val
#> 1: 2.0 foo   1
#> 2: 2.3 bar   3
#> 3: 2.0 foo   2
#> 4: 2.3 bar   2

尝试过的方法(未得到预期结果)

hplc[bioargo, on = "x", roll = "nearest"]
#>      x   z grp val
#> 1: 2.1 foo   a   1
#> 2: 2.2 bar   a   2
#> 3: 1.9 foo   b   3
#> 4: 3.0 bar   b   4

bioargo[hplc, on = "x", roll = "nearest"]
#>    grp val   x   z
#> 1:   b   3 2.0 foo
#> 2:   a   2 2.3 bar

解决方案

核心思路是先让hplc的每一行都对应bioargo的所有分组,再在每个分组内基于x做最近值匹配:

方法一:交叉连接+分组滚动匹配

# 生成hplc与所有分组的交叉连接
hplc_with_grp <- hplc[CJ(grp = unique(bioargo$grp), x = x, z = z), on = .(x, z)]

# 按grp和x做滚动连接,获取每个分组内x最接近的val
result <- hplc_with_grp[bioargo, on = .(grp, x), roll = "nearest", .(x = i.x, z, val)]

# 调整列顺序至预期格式
setcolorder(result, c("x", "z", "val"))
result
#>      x   z val
#> 1: 2.0 foo   1
#> 2: 2.0 foo   2
#> 3: 2.3 bar   3
#> 4: 2.3 bar   2

方法二:直接分组滚动连接(更简洁)

# 先对bioargo按grp和x排序,确保分组内x有序
setorder(bioargo, grp, x)

# 开启allow.cartesian,让hplc每行匹配bioargo的每个分组
bioargo[hplc, on = .(grp, x), roll = "nearest", allow.cartesian = TRUE][, .(x = i.x, z, val)]

原理说明

原尝试的问题在于:默认的滚动连接是全局匹配最近的x值,没有按grp分组处理。通过先构建交叉连接或开启allow.cartesian,确保hplc的每一行都能和bioargo的每个分组做匹配,再在分组内基于x找到最近值,就能得到预期结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:15:38