Как извлечь первые 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
                                           )]