このようなものはどうですか?(合成データは、質問からあなたについて推測できることを模倣することを目的としています)
tmp <- data.table(id = sample(1:20, 1e6, replace=TRUE),
date = as.Date(as.integer(runif(n=1e6, min = 1e4, max = 1.1e4)),
origin = as.Date("1970-01-01")),
data1 = rnorm(1e6),
data2 = rnorm(1e6),
data3 = rnorm(1e6))
> system.time(X <- tmp[, lapply(.SD, tail, 1), by = list(id, date)])
user system elapsed
1.95 0.00 1.95
> system.time(Y <- tmp[, list(tail(data1, 1)), by = list(id, date)])
user system elapsed
1.24 0.01 1.26
> system.time({
setkey(tmp, id, date)
Z <- tmp[unique(tmp)[, key(tmp), with=FALSE], mult="last"]
})
user system elapsed
0.90 0.02 0.92
同じ順序が保証された後、XとZは同じになります。
> identical(setkey(X, id, date), setkey(Z, id, date))
[1] TRUE
lapply
tail
私の列と1列の違いは、tail
あなたの列ほど劇的ではありませんが、データの構造がなければ、これ以上言うのは難しいです。
また、この方法ではほとんどの場合、キーを設定していることに注意してください。テーブルがすでにグループ化列でソートされている場合は、非常に高速になります。
> system.time(Z <- tmp[unique(tmp)[, key(tmp), with=FALSE], mult="last"])
user system elapsed
0.03 0.00 0.03
または、多列の問題を一時的な列のある1列の問題に変換することもできます。
> system.time({
tmp[, row.num := seq_len(nrow(tmp))]
W <- tmp[tmp[, max(row.num), by = list(id, date)]$V1][, row.num := NULL]
tmp[, row.num := NULL]
})
user system elapsed
0.92 0.00 1.09
> identical(setkey(X, id, date), setkey(W, id, date))
[1] TRUE