【问题标题】:remove IDs that occur x times R删除出现 x 次 R 的 ID
【发布时间】:2026-01-26 04:35:02
【问题描述】:

我有一个 df,我想删除 df 中行数少于 X 的人。例如,在这个玩具示例中,我想保留 >= 5 行的人。

df
   names  fruit
4   john   kiwi
7   john  apple
9   john banana
13  john orange
14  john  apple
2   mary orange
5   mary  apple
8   mary orange
10  mary  apple
12  mary  apple
1    tom  apple
3    tom banana
6    tom  apple
11   tom   kiwi

示例输出

df
   names  fruit
4   john   kiwi
7   john  apple
9   john banana
13  john orange
14  john  apple
2   mary orange
5   mary  apple
8   mary orange
10  mary  apple
12  mary  apple

提前致谢!

【问题讨论】:

    标签: r rows


    【解决方案1】:

    这是一个使用内置.N 值的data.table 解决方案,如?data.table 帮助文件中所述:‘.N’ is an integer, length 1, containing the number of rows in the group.

    #create a similar reproducible exmaple
    library(data.table)
    dat <- data.table(names=rep(letters[1:3],c(5,5,3)),var=1:13)
    

    删除行:

    dat[, cnt:=.N, by=names][cnt >= 5]
    

    虽然我觉得必须有一种方法可以在不分配新变量的情况下做到这一点。 ...现在感谢 cmets 中的@mnel:

    dat[,if(.N>=5).SD,by=names]
    

    如果.N 组中的行数大于或等于 5,则这实际上为by 组的每个值返回一个子数据表.SD。它几乎等同于更传统的 R 子集语法:

    dat[,.SD[.N >= 5],by=names]
    

    【讨论】:

    • dat[,if(.N&gt;=5).SD,by=names]
    • @Mnel 提出了一个很好的观点。在j 中使用if 语句的优点是它避免了在子句计算为FALSE 时调用.SD 的开销
    【解决方案2】:

    你可以像这样使用table

    df[df$names %in% names(table(df$names))[table(df$names) >= 5],]
    

    【讨论】:

    • 好东西。谢谢你。只是为了强调直接出现在 %in% 之后的“名称”是函数语法的一部分,而不是在我的 df 中引用名为“名称”的列。
    【解决方案3】:

    另一种解决方案是使用subset() 命令,如下所示:

    subset(df, ave(names, names, FUN = length) >= 5)
    

    或者,

    df[ave(df$names, df$names, FUN = length) >= 5, ]
    

    【讨论】: