一般cmets。
-
ave 方法是这里唯一保留数据初始行顺序的方法。
-
by 方法应该非常慢。我怀疑在选择组时 data.table 和 dplyr 并不比 ave 和 tapply 快多少。欢迎使用基准来证明我的错误!
base R(感谢@thelatemail 提供了前两种方法。)
1) 为每一行分配其df$ID 组的长度,我们根据长度向量进行过滤。
df[ ave(1:nrow(df), df$ID, FUN=length) > 1 , ]
2) 或者,我们按df$ID 拆分行名或编号,选择要保留哪些组的行。 tapply 返回一组行的列表,因此我们必须将unlist 它们放入单个行向量中。
df[ unlist(tapply(1:nrow(df), df$ID, function(x) if (length(x) > 1) x)) , ]
以下是一种更糟糕的方法,但更好地与您在 data.table 和 dplyr 中看到的相似:
3) 数据被df$ID 分割,保留每个数据子集,SD 如果有超过一行。 by 返回一个列表,因此我们必须将 rbind 重新组合在一起。
do.call( rbind, c(list(make.row.names = FALSE),
by(df, df$ID, FUN=function(SD) if (nrow(SD) > 1) SD )))
data.table .N 对应于by=ID 组内的nrow;而.SD 是数据的子集。
library(data.table)
setDT(df)[, if (.N>1) .SD, by=ID]
# ID Cat1 Cat2 Cat3 Cat4
# 1: A0001 358 11.2500 37428 0
# 2: A0001 279 14.6875 38605 0
# 3: A0020 367 8.8750 37797 0
# 4: A0020 339 9.6250 39324 0
dplyr n() 对应于group_by(ID) 组中的nrow。
library(dplyr)
df %>% group_by(ID) %>% filter( n() > 1 )
# Source: local data frame [4 x 5]
# Groups: ID
#
# ID Cat1 Cat2 Cat3 Cat4
# 1 A0001 358 11.2500 37428 0
# 2 A0001 279 14.6875 38605 0
# 3 A0020 367 8.8750 37797 0
# 4 A0020 339 9.6250 39324 0