разница между ddply и агрегатом

Может ли кто-нибудь помочь мне понять разницу между агрегатом и ddply на следующем примере:

Фрейм данных:

mydat <- data.frame(first = rpois(10,10), second = rpois(10,10), 
                    third = rpois(10,10), group = c(rep("a",5),rep("b",5)))

Используйте агрегат, чтобы применить функцию к части фрейма данных, разделенной на коэффициент:

aggregate(mydat[,1:3], by=list(mydat$group), mean)
  Group.1 first second third
1       a   8.8    8.8  10.2
2       b   6.8    9.4  13.4

Попробуйте использовать агрегат для другой функции (возвращает сообщение об ошибке):

aggregate(mydat[,1:3], by=list(mydat$group), function(u) cor(u$first,u$second))
Error in u$second : $ operator is invalid for atomic vectors

Теперь попробуйте то же самое с ddply (пакет plyr):

ddply(mydat, .(group), function(u) cor(u$first,u$second))
  group         V1
1     a -0.5083042
2     b -0.6329968

Все советы, ссылки, критика приветствуются.


r
person skip    schedule 05.01.2013    source источник
comment
Я думаю, вы продемонстрировали разницу. Или тут вопрос?   -  person Matthew Lundberg    schedule 06.01.2013
comment
Ну, пока я вижу разницу, я не понимаю, почему она такая. Что внутри этих функций вызывает разницу, которую я показываю?   -  person skip    schedule 06.01.2013
comment
Часть 5 programming-r -pro-bro.blogspot.com/2012/12/ содержит отличное объяснение с примером кода. По сути, ddply позволит вам использовать РАЗНЫЕ функции для каждой переменной, тогда как агрегат заставляет вас использовать одну и ту же функцию для всех передаваемых вами столбцов.   -  person d_a_c321    schedule 18.10.2013


Ответы (3)


aggregate вызывает FUN для каждого столбца независимо, поэтому вы получаете независимые средства. ddply передаст функции все столбцы. Быстрая демонстрация того, что передается в aggregate, может быть уместна:

Некоторые примеры данных для демонстрации:

d <- data.frame(a=1:4, b=5:8, c=c(1,1,2,2))

> d
  a b c
1 1 5 1
2 2 6 1
3 3 7 2
4 4 8 2

Используя функцию print и игнорируя результат команд aggregate или ddply, мы можем видеть, что передается функции на каждой итерации.

aggregate:

tmp <- aggregate(d[1:2], by=list(d$c), print)
[1] 1 2
[1] 3 4
[1] 5 6
[1] 7 8

Обратите внимание, что отдельные столбцы отправляются на печать.

ddply:

tmp <- ddply(d, .(c), print)
  a b c
1 1 5 1
2 2 6 1
  a b c
3 3 7 2
4 4 8 2

Обратите внимание, что фреймы данных отправляются на печать.

person Matthew Lundberg    schedule 05.01.2013
comment
Круто, спасибо: первые два предложения содержат именно то, что я искал. - person skip; 06.01.2013
comment
@Arun То, что я вставил, — это вывод из print в aggregate. Я опустил результат из aggregate, который не важен для этого примера. Я отредактирую ответ, чтобы лучше указать это. - person Matthew Lundberg; 06.01.2013

Вам уже сказали, почему aggregate была неправильной {базовой} функцией для функции, которая требует два вектора в качестве аргументов, но вам еще не сказали, какой подход без ddply был бы успешным.

Метод by( ... grp, FUN):

> cbind (by( mydat, mydat["group"], function(d) cor(d$first, d$second)) )
        [,1]
a  0.6529822
b -0.1964186

Метод sapply(split( ..., grp), fn)

> sapply(  split( mydat, mydat["group"]), function(d) cor(d$first, d$second)) 
         a          b 
 0.6529822 -0.1964186 
person IRTFM    schedule 05.01.2013
comment
Я всегда чувствую себя виноватым, когда прибегаю к plyr/ddply, потому что я имею в виду, что я потерпел неудачу или был слишком нетерпелив, понимая совокупность, по, или постукивая. Обратите внимание, однако, что ddply настолько общий, что может быть медленным для больших задач. Быстрая версия ddply разрабатывается здесь: github.com/hadley/dplyr . - person Dieter Menne; 06.01.2013

Ответ @MatthewLundberg очень хорош, мой это не ответ, а просто общий намек, который я использую, когда хочу посмотреть, что происходит за вызовом некоторых функций R. Я использую команду отладки browser.

aggregate(mydat[,1:3], by=list(mydat$group), 
+           function(x){
+             browser()
+             mean(x)
+           })
Called from: FUN(X[[1L]], ...)
Browse[1]> x
[1] 16 10 16 13 25

тогда для ddply

ddply(mydat, .(group), function(u) {
+   browser()
+   cor(u$first,u$second)
+   })
Called from: .fun(piece, ...)
Browse[1]> u
  first second third group
1    16      8     9     a
2    10      6     6     a
3    16      6    10     a
4    13      8    10     a
5    25     10     4     a

Редактировать отладку ошибки самостоятельно

Здесь я использую технику, чтобы увидеть, почему вы получаете сообщение об ошибке

aggregate(mydat[,1:3], by=list(mydat$group), function(u) {
+   browser()
+   cor(u$first,u$second)
+   })
Called from: FUN(X[[1L]], ...)
Browse[1]> u
[1] 16 10 16 13 25    

Как вы видите здесь, u является атомарным вектором (без имен столбцов). Поэтому, если вы попробуете

Browse[1]> u$first

Вы получаете ошибку:

Error in u$first : $ operator is invalid for atomic vectors
person agstudy    schedule 05.01.2013