3

因子のレベルごとに、現在のものを除く data.frame のすべてのサブセットで集計された値を抽出する必要があります。たとえば、数日間にわたって反応時間タスクを実行している複数の被験者がいて、すべての被験者とすべての日の平均反応時間を計算する必要がありますが、平均が計算される被験者は含まれません。現在、私は次のようにしています:

 library(lme4)
 ddply(sleepstudy, .(Subject, Days), summarise, 
       avg_rt = mean(sleepstudy[sleepstudy$Subject != Subject &
                   sleepstudy$Days == Days,"Reaction"]), .progress="text")

小さなデータセットでは問題なく動作しますが、大きなデータセットでは非常に遅くなる可能性があります. それをより速く行う方法はありますか?

4

2 に答える 2

3
#create big dataset
n <- 1e4
set.seed(1)
sleepstudy <- data.frame(Reaction=rnorm(n),Subject=1:4,Days=sort(rep((1:(n/4)),4)))


library(plyr)
system.time(
  res <- ddply(sleepstudy, .(Subject, Days), summarise, 
               avg_rt = mean(sleepstudy[sleepstudy$Subject != Subject &
                 sleepstudy$Days == Days,"Reaction"]))
)
#User      System      elapsed 
#6.532       0.013       6.556  

#use data.table for big datasets
library(data.table)

dt<- as.data.table(sleepstudy)
system.time(
 {dt[,avg_rt:=mean(Reaction),by=Days];
  dt[,n:=.N,by=Days];
  dt[,avg_rt:=(avg_rt*n-Reaction)/(n-1)]}
)
#User      System      elapsed 
#0.005       0.001       0.005 


#test if results are equal
dt2 <- as.data.table(res)
setkey(dt2,Subject,Days)
setkey(dt,Subject,Days)
all.equal(dt[,avg_rt],dt2[,avg_rt])
#[1] TRUE

非常に大きなデータセットの場合、速度の向上はより顕著になるはずです。ddply非常に遅いため、より大きなデータセットと比較できませんでした。

于 2012-09-30T12:12:08.213 に答える
0

たぶん、lapplyandの方が速いでしょうaggregate:

do.call("rbind", (lapply(unique(sleepstudy$Subject),
                         function(x)
                           cbind(Subject = x,
                                 aggregate(Reaction ~ Days,
                                           subset(sleepstudy, Subject != x),
                                           mean)))))

アップデート:

両方のコマンドを比較しsystem.timeましたが、元のコマンドの方が遅いようです。

library(lme4)
library(plyr)

system.time(
ddply(sleepstudy, .(Subject, Days), summarise, 
      avg_rt = mean(sleepstudy[sleepstudy$Subject != Subject &
                    sleepstudy$Days == Days,"Reaction"]))
)

   # user  system elapsed 
   # 0.17    0.00    0.22 

system.time(
do.call("rbind", (lapply(unique(sleepstudy$Subject),
                         function(x) 
                           cbind(Subject = x,
                                 aggregate(Reaction ~ Days,
                                           subset(sleepstudy, Subject != x),
                                           mean)))))
)


   # user  system elapsed 
   # 0.12    0.00    0.12 
于 2012-09-30T09:58:00.650 に答える