49

data.tableパッケージを使用してスライディングウィンドウ関数を実装するための最良の(最速の)方法は何ですか?

ローリング中央値を計算しようとしていますが、日付ごとに複数の行があります(2つの追加要因のため)。これは、zoorollapply関数が機能しないことを意味すると思います。ナイーブなforループを使用した例を次に示します。

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))]
}
4

4 に答える 4

9

data.table現在、ウィンドウをローリングするための特別な機能はありません。ここでの別の同様の質問に対する私の回答の詳細:

data.table 内でローリング回帰を実行する高速な方法はありますか?

ローリング中央値は興味深いです。効率的に行うには特殊な関数が必要です(以前のコメントと同じリンク):

C のローリング メディアン アルゴリズム

ここでの質問と回答の解決策は、適切な特殊化された関数 (R afaik では利用できない) とdata.table比較して、すべて非常に非効率的です。rollingmedian

于 2012-08-31T11:26:52.533 に答える
4

遅延データセットを作成し、巨大な結合を行うことで、例を 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")]

これは、このテスト データセットではかなりうまく機能しますが、私の実際のデータセットでは、8 GB の RAM で失敗します。High Memory EC2 インスタンス (17、34、または 68GB RAM) のいずれかに移動して、動作させることを試みます。メモリをあまり消費しない方法でこれを行う方法についてのアイデアをいただければ幸いです

于 2012-08-10T15:00:36.620 に答える
0

このソリューションは機能しますが、しばらく時間がかかります。

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)
于 2012-07-27T15:28:16.400 に答える