次のデータを見てみましょう。
dt <- data.table(TICKER=c(rep("ABC",10),"DEF"),
PERIOD=c(rep(as.Date("2010-12-31"),10),as.Date("2011-12-31")),
DATE=as.Date(c("2010-01-05","2010-01-07","2010-01-08","2010-01-09","2010-01-10","2010-01-11","2010-01-13","2010-04-01","2010-04-02","2010-08-03","2011-02-05")),
ID=c(1,2,1,3,1,2,1,1,2,2,1),VALUE=c(1.5,1.3,1.4,1.6,1.4,1.2,1.5,1.7,1.8,1.7,2.3))
setkey(dt,TICKER,PERIOD,ID,DATE)
ティッカー/ピリオドの組み合わせごとに、新しい列に次のものが必要です。
PRIORAVG
:現在のIDを除く、各IDの最新のVALUEの平均。ただし、180日以内である必要があります。PREV
:同じIDからの前の値。
結果は次のようになります。
TICKER PERIOD DATE ID VALUE PRIORAVG PREV
[1,] ABC 2010-12-31 2010-01-05 1 1.5 NA NA
[2,] ABC 2010-12-31 2010-01-08 1 1.4 1.30 1.5
[3,] ABC 2010-12-31 2010-01-10 1 1.4 1.45 1.4
[4,] ABC 2010-12-31 2010-01-13 1 1.5 1.40 1.4
[5,] ABC 2010-12-31 2010-04-01 1 1.7 1.40 1.5
[6,] ABC 2010-12-31 2010-01-07 2 1.3 1.50 NA
[7,] ABC 2010-12-31 2010-01-11 2 1.2 1.50 1.3
[8,] ABC 2010-12-31 2010-04-02 2 1.8 1.65 1.2
[9,] ABC 2010-12-31 2010-08-03 2 1.7 1.70 1.8
[10,] ABC 2010-12-31 2010-01-09 3 1.6 1.35 NA
[11,] DEF 2011-12-31 2011-02-05 1 2.3 NA NA
PRIORAVG
行9は1.7に等しいことに注意してください(これはVALUE
、過去180日間に別の人が行った唯一の以前の観測である行5に等しいID
)
パッケージを発見しましたdata.table
が、機能がよくわからないようです:=
。シンプルにするとうまくいくようです。各IDの以前の値を取得するには(これはこの質問の解決策に基づいています):
dt[,PREV:=dt[J(TICKER,PERIOD,ID,DATE-1),roll=TRUE,mult="last"][,VALUE]]
これはうまく機能し、約25万行のデータセットに対してこの操作を実行するのにかかる時間はわずか0.13秒です。私のベクトルスキャン関数は同じ結果を取得しますが、約30,000倍遅くなります。
さて、最初の要件があります。2番目のより複雑な要件に取り掛かりましょう。今のところ、私にとってこれまでの断食方法は、いくつかのベクトルスキャンを使用し、関数を介してplyr
関数をスローしadply
て、各行の結果を取得することです。
calc <- function(df,ticker,period,id,date) {
df <- df[df$TICKER == ticker & df$PERIOD == period
& df$ID != id & df$DATE < date & df$DATE > date-180, ]
df <- df[order(df$DATE),]
mean(df[!duplicated(df$ID, fromLast = TRUE),"VALUE"])
}
df <- data.frame(dt)
adply(df,1,function(x) calc(df,x$TICKER,x$PERIOD,x$ID,x$DATE))
の関数を作成しましたが、では機能data.frame
しないようですdata.table
。5000行のサブセットの場合、これには約44秒かかりますが、私のデータは100万行を超えています。を使用することで、これをより効率的にすることができるのだろうか:=
。
dt[J("ABC"),last(VALUE),by=ID][,mean(V1)]
これは、ABCの各IDの最新の値の平均を選択するために機能します。
dt[,PRIORAVG:=dt[J(TICKER,PERIOD),last(VALUE),by=ID][,mean(V1)]]
ただし、これは、現在のティッカー/期間だけでなく、すべてのティッカー/期間の最後のすべての値の平均を取るため、期待どおりに機能しません。したがって、すべての行が同じ平均値を取得することになります。私は何か間違ったことをしていますか、それともこれは制限:=
ですか?