【问题标题】:Keeping only the x largest groups with data.table仅使用 data.table 保留 x 个最大的组
【发布时间】:2026-02-05 22:35:01
【问题描述】:

我最近开始在 R 中使用 data.table 包,但最近偶然发现了一个我不知道如何使用 data.table 解决的问题。

样本数据:

set.seed(1)
library(data.table)
dt = data.table(group=c("A","A","A","B","B","B","C","C"),value = runif(8))

我可以用语句添加组计数

dt[,groupcount := .N ,group]

但现在我只想保留groupcount 值最大的x 个组。我们假设x=1 作为示例。

我尝试如下链接:

dt[,groupcount := .N ,group][groupcount %in% head(sort(unique(groupcount),decreasing=TRUE),1)]

但是由于 A 组和 B 组都具有三个元素,因此它们都保留在 data.table 中。我只想要 x=1 的 x 个最大的组,所以我只想要其中一个组(A 或 B)保留。我认为这可以在 data.table 的一行中完成。这是真的吗?如果是,如何?


澄清一下:这里的 x 是一个任意选择的数字。该函数还应该适用于 x=3,它会返回最大的 3 个组。

【问题讨论】:

  • 糟糕,不知道它是怎么溜进去的。已更正。
  • 另一种选择:dt[dt[order(-groupcount), unique(group)[seq_len(x)]], on = "group"]

标签: r data.table


【解决方案1】:

这是一个使用连接的方法。

x <- 1

dt[dt[, .N, by=group][order(-N)[1:x]], on="group"]
   group     value N
1:     A 0.2655087 3
2:     A 0.3721239 3
3:     A 0.5728534 3

内部 data.frame 被聚合以计算观测值,并使用 order 子集使用 x 的值检索 x 最大组的位置。然后将生成的数据框按组连接到原始数据框。

【讨论】:

  • 这样更干净
  • 谢谢lmo!这是一个非常好的解决方案。
  • dt[dt[, .N, by=group][order(-N), head(group, x)], on=.(group)]
【解决方案2】:

利用groupcount的顺序怎么样

setorder(dt, -groupcount)

x <- 1   
dt[group %in% dt[ , unique(group)][1:x] ]

#   group     value groupcount
# 1:     A 0.2655087          3
# 2:     A 0.3721239          3
# 3:     A 0.5728534          3


x <- 3
dt[group %in% dt[ , unique(group)][1:x] ]


#     group     value groupcount
# 1:     A 0.2655087          3
# 2:     A 0.3721239          3
# 3:     A 0.5728534          3
# 4:     B 0.9082078          3
# 5:     B 0.2016819          3
# 6:     B 0.8983897          3
# 7:     C 0.9446753          2
# 8:     C 0.6607978          2

## alternative syntax
# dt[group %in% unique(dt$group)[1:x] ]

【讨论】:

  • 谢谢!完全符合我的要求。所以在一行中变成:dt[,groupcount := .N ,group][group %in% dt[order(-groupcount) , unique(group)][1:x]]
  • @Florian - 你甚至可以将订单放入链中dt[,groupcount := .N, group][order(-groupcount)][ groupcount == (max(groupcount)), ][ group %in% unique(group)[1:x] ]
【解决方案3】:

我们可以的

x <- 1
dt[dt[, {tbl <- table(group)
         nm <- names(tbl)[tbl==max(tbl)]
        if(length(nm) < x) rep(TRUE, .N)
        else group %in% sample(names(tbl)[tbl==max(tbl)], x)}]]

【讨论】:

  • 嗨,akrun,如果我的问题表述不正确,请见谅。这适用于 x=1,但不适用于 x=3,在这种情况下,我希望所有组都保留。这对 data.table 也可行吗?