按群组数量筛选 data.table

Filter data.table by quantity of group

假设我有一个 data.table 喜欢

sample<-data.table(id=c(1,1,2,2,3,3,3,4,4),
                   name=c("apple","apple","orange","orange",
                          "pear","pear","pear","banana","banana"),
               atr=c("pretty","ugly","bruised","delicious",
                     "pear-shaped","bruised","infested",
                     "too-ripe","perfect"),
               N=c(10,9,15,4,5,7,7,4,12))

我想 return 本质上是 unique(sample[,list(id, name)]) 除了我还想要 atr 列作为具有最大 N 的值。在最高 N 并列的情况下我不在乎两者中的哪一个被选中,但我只想被选中一个。

这几乎可以工作 merge(sample[,list(N=max(N)),by=list(id,name1)], sample,by=c("id","name1","N")),但由于 pear 有两个 atr 值,这两个 return 的两个 pear 最大。除了它没有给出预期的结果,我还 assume/hope 有一种不涉及连接的方法。

在平局的情况下,您可以只使用 atr[N == max(N)][1] 到 return,就像这样 -

library(data.table)

sample[, .(atr = atr[N == max(N)][1]), by = .(id, name)]
#    id   name     atr
# 1:  1  apple  pretty
# 2:  2 orange bruised
# 3:  3   pear bruised
# 4:  4 banana perfect

注意: 正如 Frank 指出的 atr[N == max(N)][1] 也只是 atr[which.max(N)]

我会用 order:

> unique(sample[order(-N), .(id, name, atr)], by = c("id", "name"))
   id   name     atr
1:  2 orange bruised
2:  4 banana perfect
3:  1  apple  pretty
4:  3   pear bruised

如果要保持整体排序,只需使用order(id, name, -N)即可。

你也可以把它分成两行:

setorder(sample, -N) #done by reference, as with all set* functions in data.table
unique(sample[ , .(id, name, atr)], by = c("id", "name"))

或者可能更好,具体取决于您的最终目标:

setkey(setorder(sample, -N), id, name)
unique(sample[ , .(id, name, atr)])

(注意:最后的顺序很重要,因为首先使用 setorder 会覆盖 NULL 的键)