Как извлечь первые n строк на группу?
У меня есть data.table dt
. Этот data.table сортируется сначала по date
столбца (моя переменная группировки), а затем по age
столбца:
library(data.table)
setkeyv(dt, c("date", "age")) # Sorts table first by column "date" then by "age"
> dt
date age name
1: 2000-01-01 3 Andrew
2: 2000-01-01 4 Ben
3: 2000-01-01 5 Charlie
4: 2000-01-02 6 Adam
5: 2000-01-02 7 Bob
6: 2000-01-02 8 Campbell
Мой вопрос: мне интересно, возможно ли извлечь первые 2 строки для каждой уникальной даты? Или сформулировано более широко:
Как извлечь первые n строк в каждой группе?
В этом примере результат в dt.f
будет:
> dt.f = ???????? # function of dt to extract the first 2 rows per unique date
> dt.f
date age name
1: 2000-01-01 3 Andrew
2: 2000-01-01 4 Ben
3: 2000-01-02 6 Adam
4: 2000-01-02 7 Bob
ps Вот код для создания вышеупомянутого data.table:
install.packages("data.table")
library(data.table)
date <- c("2000-01-01","2000-01-01","2000-01-01",
"2000-01-02","2000-01-02","2000-01-02")
age <- c(3,4,5,6,7,8)
name <- c("Andrew","Ben","Charlie","Adam","Bob","Campbell")
dt <- data.table(date, age, name)
setkeyv(dt,c("date","age")) # Sorts table first by column "date" then by "age"
Ответы
Ответ 1
yep, просто используйте .SD
и проиндексируйте его по мере необходимости.
DT[, .SD[1:2], by=date]
date age name
1: 2000-01-01 3 Andrew
2: 2000-01-01 4 Ben
3: 2000-01-02 6 Adam
4: 2000-01-02 7 Bob
Отредактировано в соответствии с предложением @eddi.
Предложение @eddi указано на:
Используйте это вместо этого для скорости:
DT[DT[, .I[1:2], by = date]$V1]
# using a slightly larger data set
> microbenchmark(SDstyle=DT[, .SD[1:2], by=date], IStyle=DT[DT[, .I[1:2], by = date]$V1], times=200L)
Unit: milliseconds
expr min lq median uq max neval
SDstyle 13.567070 16.224797 22.170302 24.239881 88.26719 200
IStyle 1.675185 2.018773 2.168818 2.269292 11.31072 200
Ответ 2
Вероятно, не самый быстрый метод, но он обеспечивает некоторую гибкость, если вы не используете ключевые переменные и нуждаетесь в большей гибкости. Изменяя выбранный Row.ID
количество первых объектов может быть скорректировано по мере необходимости.
dt[, .( age
, name
, Row.ID = rank(age)
)
, by = list(date)][Row.ID %in% (1:2), .(date
, age
, name
)]