Pour chaque niveau de valeurs globales de facteur sur tous les niveaux, à l'exception de l'actuel

StackOverflow https://stackoverflow.com//questions/12660211

  •  11-12-2019
  •  | 
  •  

Question

Pour chaque niveau de facteur, j'ai besoin d'extraire des valeurs agrégées sur tous les sous-ensembles de données. Sauf le présent.Par exemple, plusieurs sujets effectuent une tâche de temps de réaction pendant plusieurs jours et j'ai besoin de calculer du temps de réaction moyen pour tous les sujets et tous les jours, mais sans inclure le sujet pour lequel la moyenne est calculée.Actuellement, je le fais comme ceci:

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

Cela fonctionne bien pour les petits ensembles de données, mais pour les grands, cela peut être très lent.Y a-t-il un moyen de le faire plus vite?

Était-ce utile?

La solution

#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

Pour de très grands ensembles de données, le gain de vitesse devrait être plus prononcé.Je ne pouvais tout simplement pas comparer avec des jeux de données plus importants puisque ddply est si lent.

Autres conseils

Maybe it's faster with lapply and aggregate:

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

Update:

I compared both commands with system.time and it appears the original is slower.

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 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top