2

私は非常に大きなデータフレームを持っており、私の目標はユーザー ID ごとに累積 USD をリストすることです。データフレームは次のようになりますが、はるかに大きくなります。

dt<-sample(seq(as.Date("2013-01-01"),as.Date("2013-05-01"),by="days"),10)
s<-c(rep(5252525,5),rep(1313131,5))
usd<-round(rnorm(10,100),2)
money<-data.frame(dt,s,usd)
money<-money[order(money$dt),]
money$Cumulative<-NA
users<-unique(money$s)

for ループから始めましたが、非常に遅かったです。

for (i in 1:length(users)){
    temp=which(money$s==users[i])
    money$Cumulative[temp]=cumsum(money$usd[temp])
}

data.table を使用して全体的な速度を向上させることができることを StackOverflow で読みましたが、これは多少役に立ちました。

money<-data.table(money)
setkey(money,s)

for (i in 1:length(users)){
    temp=which(money$s==users[i])
    money$Cumulative[temp]=cumsum(money$usd[temp])
}

この計算をもっと速くしたい。次に何をすべきですか?

4

2 に答える 2

1

data.tableオプションを探しているようです。

ジョシュアが提案した方法を使用し、おもちゃのデータを使用すると誤解を招く可能性があることを指摘します (つまり、同様の方法は最小限のデータセットlil_moneyでは同様に機能しますが、より現実的なデータセットでは機能しませんmoney):

結果

Unit: microseconds
              expr     min      lq  median      uq       max neval
 useAve(lil_money) 694.269 730.491 741.358 756.753 13687.951  1000
  useBy(lil_money) 709.664 748.603 759.470 775.770  5341.338  1000

Unit: milliseconds
          expr       min        lq    median        uq       max neval
 useAve(money) 3940.8970 3966.0950 4002.4319 4090.3967 4145.2672    10
  useBy(money)  105.7129  106.5789  109.6566  117.2939  122.1414    10

Identical output: TRUE

コード

require(microbenchmark)
require(data.table)

start <- as.Date("2001-01-01")
money <- CJ(s=1:1e4, dt=start + 0:1e3)[, usd := runif(.N)]

lil_money <- money[s < 10 & dt < start + 10]

useAve <- function(DT) { DT[, cum_ave := ave(usd, s, FUN=cumsum)] }
useBy <- function(DT) { DT[, cum_by := cumsum(usd), by=s] }

print(microbenchmark(useAve(lil_money), useBy(lil_money),  times=1000))
print(microbenchmark(useAve(money), useBy(money),  times=10))

cat("Identical output:", identical(money$cum_ave, money$cum_by))
于 2013-07-26T23:24:33.390 に答える