لكل مستوى من القيم الإجمالية للعامل على جميع المستويات باستثناء المستوى الحالي

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

  •  11-12-2019
  •  | 
  •  

سؤال

بالنسبة لكل مستوى من العوامل، أحتاج إلى استخراج القيم المجمعة على جميع المجموعات الفرعية من data.frame باستثناء المجموعة الحالية.على سبيل المثال، هناك عدة أشخاص يقومون بمهمة وقت رد الفعل خلال عدة أيام، وأحتاج إلى حساب متوسط ​​وقت رد الفعل لجميع المواد وجميع الأيام، ولكن لا يشمل الشخص الذي تم حساب المتوسط ​​له.حاليا أفعل ذلك مثل هذا:

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

إنه يعمل بشكل جيد مع مجموعات البيانات الصغيرة، ولكن بالنسبة للمجموعات الكبيرة يمكن أن يكون بطيئًا جدًا.هل هناك طريقة للقيام بذلك بشكل أسرع؟

هل كانت مفيدة؟

المحلول

#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 بطيء جدًا.

نصائح أخرى

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 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top