r data.tableスライディングウィンドウ
-
12-12-2019 - |
質問
データを使用してスライディングウィンドウ機能を実装するための最良の(最速)方法は何ですか。
私はローリング中央値を計算しようとしていますが、日付ごとに複数の行を持っています(2つの追加要因による)、動物園のRollapply機能が機能しないことを意味します。ここでは、ループ用のナイーブを使用した例です。
library(data.table)
df <- data.frame(
id=30000,
date=rep(as.IDate(as.IDate("2012-01-01")+0:29, origin="1970-01-01"), each=1000),
factor1=rep(1:5, each=200),
factor2=1:5,
value=rnorm(30, 100, 10)
)
dt = data.table(df)
setkeyv(dt, c("date", "factor1", "factor2"))
get_window <- function(date, factor1, factor2) {
criteria <- data.table(
date=as.IDate((date - 7):(date - 1), origin="1970-01-01"),
factor1=as.integer(factor1),
factor2=as.integer(factor2)
)
return(dt[criteria][, value])
}
output <- data.table(unique(dt[, list(date, factor1, factor2)]))[, window_median:=as.numeric(NA)]
for(i in nrow(output):1) {
print(i)
output[i, window_median:=median(get_window(date, factor1, factor2))]
}
. 解決
data.table
は、現在ローリングウィンドウの特別な機能を持っていません。ここで別の類似の質問に対する私の答えのさらに詳細:
ローリング中央値は面白いです。効率的に行う特別な機能(以前のコメントと同じリンク)が必要です。
ここでの問題と回答のdata.table
ソリューションは、適切な専用のrollingmedian
関数(R AFAIKには利用できません)に対して、すべて非常に非効率的です。
他のヒント
遅延データセットを作成し、巨大な参加を行うことで、例を1.4秒に取得できます。
df <- data.frame(
id=30000,
date=rep(as.IDate(as.IDate("2012-01-01")+0:29, origin="1970-01-01"), each=1000),
factor1=rep(1:5, each=200),
factor2=1:5,
value=rnorm(30, 100, 10)
)
dt2 <- data.table(df)
setkeyv(dt, c("date", "factor1", "factor2"))
unique_set <- data.table(unique(dt[, list(original_date=date, factor1, factor2)]))
output2 <- data.table()
for(i in 1:7) {
output2 <- rbind(output2, unique_set[, date:=original_date-i])
}
setkeyv(output2, c("date", "factor1", "factor2"))
output2 <- output2[dt]
output2 <- output2[, median(value), by=c("original_date", "factor1", "factor2")]
.
このテストデータセットではかなりうまく機能しますが、私の実際のものには8GBのRAMで失敗します。私はそれを作業するために(17,34または68GBのRAMを持つ)高メモリEC2インスタンスの1つに移動しようとします。より少ないメモリ集中的な方法でこれを行う方法についてのアイデアは存在するでしょう
この解決策は機能しますが、しばらく時間がかかります。
df <- data.frame(
id=30000,
date=rep(seq.Date(from=as.Date("2012-01-01"),to=as.Date("2012-01-30"),by="d"),each=1000),
factor1=rep(1:5, each=200),
factor2=1:5,
value=rnorm(30, 100, 10)
)
myFun <- function(dff,df){
median(df$value[df$date>as.Date(dff[2])-8 & df$date<as.Date(dff[2])-1 & df$factor1==dff[3] & df$factor2==dff[4]])
}
week_Med <- apply(df,1,myFun,df=df)
week_Med_df <- cbind(df,week_Med)
. 所属していません StackOverflow