2

金融センターからメッセージを削除するという金融問題に取り組んでいます。私は data.table を使用していますが、そのパフォーマンスと扱いやすさに非常に満足しています。

ただし、data.table のすべての機能を改善して使用するにはどうすればよいか、常に自問自答しています。

これが私のタスクの例です:

set.seed(1)
DT <- data.table(SYM = c(rep("A", 10), rep("B", 12)), PRC = format(rlnorm(22, 2), digits = 2), VOL = rpois(22, 312), ID = c(seq(1000, 1009), seq(1004, 1015)), FLAG = c(rep("", 8), "R", "A", rep("", 4), "R", rep("", 7)))
DT$PRC[9] <- DT$PRC[6]
DT$PRC[7] <- DT$PRC[6] 
DT$VOL[9] <- DT$VOL[6]
DT$VOL[7] <- DT$VOL[6]
DT$PRC[15] <- DT$PRC[13]
DT$VOL[15] <- DT$VOL[13]
## See the original dataset
DT
## Set the key
setkey(DT, "SYM", "PRC", "VOL", "FLAG")
## Get all rows, that match a row with FLAG == "R" on the given variables in the list
DT[DT[FLAG == "R"][,list(SYM, PRC, VOL)]]
## Remove these rows from the dataset
DT <- DT[!DT[FLAG == "R"][,list(SYM, PRC, VOL)]]
## See the modified data.table
DT

私の質問は今:

  1. これは私のタスクを実行するための効率的な方法ですか、それとももっと「data.table」スタイルが存在しますか? キーは効率的に設定されていますか?
  2. 一致する3つの変数(ここではSYM、PRC、VOL)だけでなく、除外のようなものが存在する場合(data.frameスタイルを使用できることは知っていますが、 data.table のよりエレガントな方法があるかどうかを知りたい)?
  3. 最後のコマンドのコピーとは何ですか? remove row by referenceのスレッドに従って、コピーが唯一の方法だと思います。いくつかのタスクがある場合、それらをある方法で組み合わせて、各タスクのコピーを避けることはできますか?
4

2 に答える 2

1

この操作を実行するためのキーのみを設定している場合は、@eddi の回答が最適で読みやすいです。

setkey(DT, SYM, PRC, VOL)
# ^ as in @eddi's answer, since you are not using the rest of the key
microbenchmark(
    notjoin=DT[!DT[FLAG == "R"][,list(SYM, PRC, VOL)]],
    logi_not=DT[!DT[,rep(any(FLAG=='R'),.N),by='SYM,PRC,VOL']$V1],
    idx_not=DT[!DT[,if(any(FLAG=='R')){.I}else{NULL},by='SYM,PRC,VOL']$V1],
    SD=DT[,if(!any(FLAG=='R')){.SD}else{NULL},by='SYM,PRC,VOL'],
    eddi=DT[!DT[FLAG == "R"]],
    times=1000L
)   

結果:

Unit: milliseconds
     expr      min       lq   median       uq       max neval
  notjoin 4.983404 5.577309 5.715527 5.903417 66.468771  1000
 logi_not 4.393278 4.960187 5.097595 5.273607 66.429358  1000
  idx_not 4.523397 5.139439 5.287645 5.453129 15.068991  1000
       SD 3.670874 4.180012 4.308781 4.463737  9.429053  1000
     eddi 2.767599 3.047273 3.137979 3.255680 11.970966  1000

一方、上記のオプションのいくつかでは、キーによるグループ化を操作に含める必要はありません。あなたがどちらか...

  • キー以外のグループ(変更したくない)を使用してこれを1回実行している、または
  • コピー操作を実行して行を削除する前に、異なるグループ化を使用してこのようないくつかの操作を実行したいnewDT <- DT[...](OP のポイント 3 で述べたように)。

.

setkey(DT,NULL)
shuffDT <- DT[sample(1:nrow(DT))] # not realistic, of course
# same benchmark with shuffDT, but without methods that require a key
# Unit: milliseconds
#      expr      min       lq   median       uq      max neval
#  logi_not 4.466166 5.120273 5.298174 5.562732 64.30966  1000
#   idx_not 4.623821 5.319501 5.517378 5.799484 15.57165  1000
#        SD 4.053672 4.448080 4.612213 4.849505 66.76140  1000

これらの場合、OP と eddi のメソッドは使用できません (参加にはキーが必要なため)。1 回限りの操作の場合は、使用した.SD方が速いようです。複数の基準でサブセット化するには、コピーを作成する前に保持/削除する行を追跡する必要がありますnewDT <- DT[!union(badrows1,badrows2,...)]

DT[,rn:=1:.N] # same as .I
badflagrows <- DT[,if(any(FLAG=='R')){rn}else{NULL},by='SYM,PRC,VOL']$V1
# fill in next_cond, next_grp
badnextrows <- DT[!badflagrows][,
    if(any(next_cond)){rn}else{NULL},by='next_grp']$V1

おそらく、論理サブセット (ベンチマークの「logi_not」) を使用して同様のことを行うことができますが、これは少し高速です。

于 2013-10-17T16:13:52.400 に答える
1

キーを に設定している理由がわかりFLAGません

setkey(DT, SYM, PRC, VOL)

DT[!DT[FLAG == "R"]]
于 2013-10-17T16:24:45.013 に答える