能否在data.table中按聚合结果排序?索引实现问题咨询
在data.table中按聚合结果排序的正确姿势
好问题!这确实能帮你吃透data.table的核心执行逻辑~
首先得明确:你之前的两行代码写法完全没问题,而且setorder()是原地排序,性能还特别好,其实很推荐。不过你好奇的单行实现和报错原因,咱来拆解清楚:
为什么你的单行代码会报错?
data.table的语法x[i, j, by]是有固定执行顺序的:
- 先处理
i部分:对原始的flights表做行筛选、排序等操作,这时候只能用原始表中存在的列(比如distance) - 再按
by指定的字段分组 - 最后执行
j部分:对每个分组计算聚合,生成新的列(比如你定义的miles)
你写的flights[order(-miles), .(miles = sum(distance)), by = "carrier"]里,order(-miles)是在i阶段执行的,但这时候miles还没生成(它是j阶段才会出现的聚合列),原始的flights表根本没有这个字段,自然会报错。
正确的单行实现方式
如果想把聚合和排序写成一行,利用data.table的链式操作就可以了——因为每次[]返回的都是data.table对象,所以可以直接在后面追加排序操作:
mbc <- flights[, .(miles = sum(distance)), by = carrier][order(-miles)]
这个写法和你原来的两行代码逻辑完全一致:先完成聚合得到包含carrier和miles的表,再对这个结果表按-miles排序。
额外小技巧:更高效的原地排序
如果你追求极致性能,还是推荐你原来的两行写法,因为setorder(mbc, -miles)是原地修改原表,不需要额外复制数据,比[order()]的内存效率更高。尤其是处理大表的时候,这个差异会很明显。
内容的提问来源于stack exchange,提问作者Tim Hoolihan
相关产品推荐
相关产品推荐

