Во-первых, две альтернативы base
. Один полагается на table
, а другой на ave
и length
. Затем два пути data.table
.
table
tt <- table(df$name)
df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]
Если вы хотите шаг за шагом пройти:
# count each 'name', assign result to an object 'tt'
tt <- table(df$name)
# which 'name' in 'tt' occur more than three times?
# Result is a logical vector that can be used to subset the table 'tt'
tt < 3
# from the table, select 'name' that occur < 3 times
tt[tt < 3]
# ...their names
names(tt[tt < 3])
# rows of 'name' in the data frame that matches "the < 3 names"
# the result is a logical vector that can be used to subset the data frame 'df'
df$name %in% names(tt[tt < 3])
# subset data frame by a logical vector
# 'TRUE' rows are kept, 'FALSE' rows are removed.
# assign the result to a data frame with a new name
df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]
ave
и length
Как предложено @flodel:
df[ave(df$x, df$name, FUN = length) < 3, ]
data.table
: .N
и .SD
: library(data.table)
setDT(df)[, if (.N < 3) .SD, by = name]
data.table
: .N
и .I
: setDT(df)
df[df[, .I[.N < 3], name]$V1]
См. также соответствующий Q & amp; A Рассчитайте количество наблюдений / строк на группу и добавьте результат в кадр данных .
Использование пакета dplyr
:
df %>%
group_by(name) %>%
filter(n() < 4)
df[ave(df$x, df$name, FUN = length) < 3, ]
– flodel 26 November 2013 в 04:03[.data.table
не вызывается для каждой группы вdf[, if (.N < 3) .SD, by = name]
. (В отличие от вопроса, который вы связываете, где.SD
является подмножеством). Другой вариант не работает быстрее. Тест сdf <- data.table(name = sample(1:1e6, 3e6, T), a = runif(30), b = runif(30), c = runif(30)); microbenchmark( df[, if (.N < 3) .SD, by = name], df[df[, .I[.N < 3], name]$V1] )
– Ryan 9 May 2018 в 16:50