使用`data.table`来获取基于变量的第一个子组

Hen*_*und 4 r data.table

考虑一个由分组变量(此处id)和有序变量(此处date)组成的数据集

(df <- data.frame(
  id = rep(1:2,2),
  date = 4:1
))
#   id date
# 1  1    4
# 2  2    3
# 3  1    2
# 4  2    1
Run Code Online (Sandbox Code Playgroud)

我想知道最简单的方法是data.table做相同的dplyr代码:

library(dplyr)
df %>%
  group_by(id) %>%
  filter(min_rank(date)==1)
# Source: local data frame [2 x 2]
# Groups: id
# 
#   id date
# 1  1    2
# 2  2    1
Run Code Online (Sandbox Code Playgroud)

即根据每个id获得第一个date.

基于类似的stackoverflow问题(使用data.table为组的每个元素创建一个"索引"),我想出了这个

library(data.table)
dt <- data.table(df)
setkey(dt, id, date)
for(k in unique(dt$id)){
  dt[id==k, index := 1:.N]
}
dt[index==1,]
Run Code Online (Sandbox Code Playgroud)

但似乎应该有一个单行.不熟悉data.table我想到这样的事情

dt[,,mult="first", by=id]
Run Code Online (Sandbox Code Playgroud)

应该工作,但唉!代码的最后一段似乎应该分组id然后取第一个(由于我以这种方式设置了密钥,因此id将在内部确定date.)


编辑

感谢阿南达·马托(Ananda Mahto),这支单人班轮现将成为我的data.table保留曲目

dt[,.SD[1], by=id]
#    id date
# 1:  1    2
# 2:  2    1
Run Code Online (Sandbox Code Playgroud)

A5C*_*2T1 5

直接使用您的来源data.frame,您可以尝试:

setkey(as.data.table(df), id, date)[, .SD[1], by = id]
#    id date
# 1:  1    2
# 2:  2    1
Run Code Online (Sandbox Code Playgroud)

扩展您的原创想法,您可以这样做:

dt <- data.table(df)
setkey(dt, id, date)
dt[, index := sequence(.N), by = id][index == 1]
#    id date index
# 1:  1    2     1
# 2:  2    1     1
Run Code Online (Sandbox Code Playgroud)

可能是在某种程度上,大卫对于headvs 是正确的[1],但我不确定那将是什么规模.

set.seed(1)
nrow <- 10000
ncol <- 20

df <- data.frame(matrix(sample(10, nrow * ncol, TRUE), nrow = nrow, ncol = ncol))

fun1 <- function() setkey(as.data.table(df), X1, X2)[, head(.SD, 1), by = X1]
fun2 <- function() setkey(as.data.table(df), X1, X2)[, .SD[1], by = X1]

library(microbenchmark)
microbenchmark(fun1(), fun2())
# Unit: milliseconds
#    expr       min        lq      mean    median        uq      max neval
#  fun1() 12.178189 12.496777 13.400905 12.808523 13.483545 30.28425   100
#  fun2()  4.474345  4.554527  4.948255  4.620596  4.965912  8.17852   100
Run Code Online (Sandbox Code Playgroud)