使用by=.EACHI时data.table为何存在重复列名?
data.table 不等连接 +
by=.EACHI 重复列名问题解答 问题背景
在计算每个时间戳过去10秒内记录的滚动中位数时,使用by=.EACHI的不等连接写法会出现重复的time列,而普通连接会自动重命名重复列,由此衍生三个技术问题:
1. 为何使用by=.EACHI时未自动修复重复列名?
普通连接(无by=.EACHI)会返回左右表的所有匹配行,此时若出现列名重复,data.table会给右侧i表的重复列添加.1后缀(如time.1),目的是区分来自左右表的同名列。
但使用by=.EACHI时,执行的是按i表每行的连接组进行聚合,返回的不是原表的列,而是on参数中每个不等条件对应的边界值。由于你在on里用了同一列的两个独立条件(time >= time10和time <= time),这两个条件对应的边界值都会被作为分组键返回,data.table认为这是你明确需要的两个独立结果,因此不会自动重命名——这不是表间的重复列,而是两个不同条件的输出。
2. 重复time列的底层机制是什么,如何区分并访问它们?
底层机制
当X[Y, on=..., by=.EACHI]执行时,by=.EACHI会以Y表的每一行作为分组依据,计算该行在X表中满足on条件的所有行的聚合结果。此时返回的重复列,对应on参数中每个条件的边界值:
- 第一个
time列:对应on中第一个条件time >= time10的右侧值(即Y表的time10,也就是time-10) - 第二个
time列:对应on中第二个条件time <= time的右侧值(即Y表的time)
区分与访问方式
- 提前重命名(推荐):在
on参数中直接给条件命名,从根源避免重复列:
结果会直接生成dt[dt, on = .(lower_bound = time >= time10, upper_bound = time <= time), .(N = .N), by = .EACHI]lower_bound和upper_bound列,无重复问题。 - 位置索引访问:对结果表按列位置访问,比如
result[[1]]取第一个time,result[[2]]取第二个:res <- dt[dt, on = .(time >= time10, time <= time), .N, by = .EACHI] res[, lower := V1] res[, upper := V2] - 用
get()指定环境:通过指定位置区分两个同名列:dt[dt, on = .(time >= time10, time <= time), .(N = .N, lower = get("time"), upper = get("time", pos = 2)), by = .EACHI]
3. 是否有关于该特性的优质官方或技术文档可参考?
- 官方帮助页:直接查看
?data.table,重点关注on参数、by=.EACHI的说明,里面有不等连接的基础示例。 - 官方Vignettes:《Joins》专题文档详细讲解了等值连接、不等连接的用法,以及
by=.EACHI的聚合场景。 - GitHub Wiki:data.table的GitHub仓库Wiki中的《Advanced Joins》部分,包含更多复杂的不等连接+聚合的实战案例。
内容的提问来源于stack exchange,提问作者Noskario
相关产品推荐
相关产品推荐

