在R中按组和条件求列的最大值(基于data.table)
用data.table实现同组且days大于指定值的最大值匹配
嗨,这个需求刚好是data.table擅长处理的非等值连接场景,我给你两种实用的解决思路,附带示例代码和解释:
先构造示例数据
首先我们先创建模拟的表A和表B,方便你测试代码:
library(data.table) # 示例表A A <- data.table( ID_A = c("A1", "A2", "A3"), days = c(5, 3, 7), group = c("X", "Y", "X") ) # 示例表B B <- data.table( ID_B = c("B1", "B2", "B3", "B4", "B5"), days = c(3, 6, 8, 2, 9), group = c("X", "X", "X", "Y", "Y"), value_of_interest = c(10, 20, 15, 5, 25) )
方法1:直接使用非等值连接(直观易懂)
这种方法用data.table的非等值连接语法,直接为表A的每一行匹配表B中符合条件的行,并计算最大值:
# 给表A添加max_value_of_interest列 A[, max_value_of_interest := B[A, on = .(group, days > days), max(value_of_interest), by = .EACHI]$V1]
代码解释
B[A, ...]:以表A为查询表,在表B中查找匹配行on = .(group, days > days):匹配条件是两组group相等,且表B的days大于表A当前行的days(第一个days是表B的列,第二个是表A的列)by = .EACHI:表示对表A的每一行(每个匹配组)单独计算最大值- 最后提取计算出的最大值
$V1,赋值给表A的新列
运行后表A的结果:
ID_A days group max_value_of_interest 1: A1 5 X 20 2: A2 3 Y 25 3: A3 7 X 15
方法2:预计算累积最大值(大数据量更高效)
如果你的数据量很大,重复计算最大值会影响效率,这时候可以先对表B做预处理,计算每个分组内的反向累积最大值,再做匹配:
# 步骤1:对表B按group和days升序排序,计算反向累积最大值 B_sorted <- B[order(group, days), # reverse_cum_max表示当前行及之后所有行的value_of_interest最大值(即days>=当前days的最大值) reverse_cum_max := rev(cummax(rev(value_of_interest))), by = group] # 步骤2:匹配表A,取第一个days>A.days的行的reverse_cum_max A[, max_value_of_interest := B_sorted[A, on = .(group, days > days), x.reverse_cum_max, mult = "first"]]
代码解释
- 预计算
reverse_cum_max:通过rev(cummax(rev(...)))实现从后往前的累积最大值,这样每个位置的值就是该分组中所有days>=当前days的value_of_interest的最大值 mult = "first":因为表B已经按days升序排序,第一个满足days>A.days的行的reverse_cum_max,就是所有days>A.days的行的最大值,直接取这个值即可
这种方法避免了对表A的每一行都重新计算最大值,数据量越大,效率提升越明显。
内容的提问来源于stack exchange,提问作者Sarah
相关产品推荐
相关产品推荐

