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

为何在data.table中用所有列分组时.SD会生成空表?

关于data.table中by包含所有列时.SD为空表的疑问

我在Stack Overflow的相关评论里看到:当by参数用到所有列时,.SD会变成空的data.table,这个逻辑我搞不懂,举个例子:

library(data.table)
dt <- data.table(x = c(1,1,2,2), y = c(1,2,3,3))
dt

输出:

x y
1: 1 1
2: 1 2
3: 2 3
4: 2 3

执行dt[, .SD[.N], by = .(x, y)]得到空表:

Empty data.table (0 rows and 2 cols): x,y

我本来以为这段代码的输出应该和下面这段代码的结果一致:

dt[, keep := (1:.N) == .N, by = .(x, y)]
dt[keep == 1, c("x", "y")]

输出:

x y
1: 1 1
2: 1 2
3: 2 3

问题原因与解决方法

为什么会得到空表?

data.table的规则是:.SD代表除了by里的分组列之外的所有列。当你把所有列都设为分组列时,.SD就没剩下其他列能包含了,直接变成空表。这时候.SD[.N]就是从空表里取第N行,结果当然是空的。

怎么拿到你想要的结果?

要是想按所有列分组后保留每组的最后一行,有几种更直接的写法:

  • 用unique()加fromLast = TRUE,直接去重并留每组最后一行:

    unique(dt, by = c("x", "y"), fromLast = TRUE)
    
  • 用.I获取每组最后一行的索引,再提取对应行:

    dt[dt[, .I[.N], by = .(x, y)]$V1]
    
  • 或者直接在j里返回分组列的最后一行(毕竟分组列本身就在by里,不用从.SD取):

    dt[, .(x = last(x), y = last(y)), by = .(x, y)]
    

这几种写法都能得到你期望的输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 02:43:20