8

私は次のことをして驚いた:

R) system.time(lastOrder <- order[,lapply(.SD,tail,1),by="TRADER_ID,EXEC_IDATE"]);
utilisateur     système      écoulé 
       1.45        0.00        1.53 
R) nrow(order)
[1] 75301
R) ncol(order)
[1] 23

とても長いと思ってやった

R) system.time(lastOrder <- order[,list(test=tail(EXEC_IDATE,1)),by="TRADER_ID,EXEC_IDATE"]);
utilisateur     système      écoulé 
       0.14        0.00        0.14 

私が理解している限り、選択するすべての行を知っていて、ほとんどの作業が完了している場合、これをすべての列に適用する理由が10倍長くなる理由がわかりません。コードの最初のビットで何か間違ったことをしていますか?これは、グループごとに最後の行を選択するために私が知っている唯一の方法です

4

2 に答える 2

10

グループ別の最後の行:

DT[, .SD[.N], by="TRADER_ID,EXEC_IDATE"]            # (1)

または、より高速です(.SD速度を上げるために、可能な限り使用を避けてください):

w = DT[, .I[.N], by="TRADER_ID,EXEC_IDATE"][[3]]    # (2)
DT[w]

次の機能要求により、アプローチ(1)がアプローチ(2)と同じくらい速くなることに注意してください。

FR#2330 .SD [i]クエリを最適化して、エレガンスを維持しながら、変更せずに高速化します。

于 2013-01-04T10:56:41.627 に答える
3

このようなものはどうですか?(合成データは、質問からあなたについて推測できることを模倣することを目的としています)

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
于 2013-01-03T17:38:43.603 に答える