2010-11-27 6 views
3

J'essaie de transmettre une fonction (weight.func) à une fonction différente (wrapper) qui appelle ddply. Je veux ddply utiliser cette fonction (weight.func) dans le cadre de ses calculs. J'obtiens la sortie que je veux quand weight.func est défini 'globalement' mais pas quand il est passé en tant que fonction anonyme à l'encapsuleur. Puis-je demander à ddply de faire ce que je veux? Voici un exemple de code:plyr résume seulement les fonctions globales des appels

> print(sampleData) 
    studentId problem part  workerId rating 
1  8001 problem26 partA A127R5QI5OGBIK 0.0 
2  8001 problem26 partA A1FCLYRBAB430F 0.0 
3  8001 problem26 partA A25FZQY34C6RVO 0.0 
4  8001 problem26 partA A3G0MO562MHMZ3 0.5 
5  8001 problem26 partA A3RB9ZOIUC3NWG 2.0 
6  8001 problem26 partB A1FCLYRBAB430F 0.5 
7  8001 problem26 partB A1XRDZKSJBWY8Q 0.5 
8  8001 problem26 partB A22CRWMZUX7FFR 0.5 
9  8001 problem26 partB A25FZQY34C6RVO 1.0 
10  8001 problem26 partB A3G0MO562MHMZ3 0.5 
11  8001 problem27 partA A1ET309DW6M2XA 2.0 
12  8001 problem27 partA A1FCLYRBAB430F 0.0 
13  8001 problem27 partA A22CRWMZUX7FFR 0.0 
14  8001 problem27 partA A25FZQY34C6RVO 0.0 
15  8001 problem27 partA A3G0MO562MHMZ3 0.0 
16  8001 problem27 partB A1FCLYRBAB430F 1.0 
17  8001 problem27 partB A22CRWMZUX7FFR 0.0 
18  8001 problem27 partB A25FZQY34C6RVO 0.0 
19  8001 problem27 partB A2U9676210WST5 0.0 
20  8001 problem27 partB A3G0MO562MHMZ3 0.0 
21  8002 problem26 partA A127R5QI5OGBIK 0.0 
22  8002 problem26 partA A1FCLYRBAB430F 0.5 
23  8002 problem26 partA A22CRWMZUX7FFR 0.0 
24  8002 problem26 partA A25FZQY34C6RVO 2.0 
25  8002 problem26 partA A3G0MO562MHMZ3 0.5 
26  8002 problem26 partB A17EHJZNJGNRAN 2.0 
27  8002 problem26 partB A1FCLYRBAB430F 0.0 
28  8002 problem26 partB A2IPRDTE6B4TAB 0.0 
29  8002 problem26 partB A3G0MO562MHMZ3 0.0 
30  8002 problem26 partB A6SON3OS15XKA 0.0 
31  8002 problem27 partA A1FCLYRBAB430F 0.0 
32  8002 problem27 partA A25FZQY34C6RVO 0.0 
33  8002 problem27 partA A2IPRDTE6B4TAB 0.0 
34  8002 problem27 partA A2U9676210WST5 0.0 
35  8002 problem27 partA A3G0MO562MHMZ3 0.0 
36  8002 problem27 partB A1FCLYRBAB430F 0.0 
37  8002 problem27 partB A1V52SSKROBV8E 2.0 
38  8002 problem27 partB A25FZQY34C6RVO 2.0 
39  8002 problem27 partB A2IPRDTE6B4TAB 0.0 
40  8002 problem27 partB A3G0MO562MHMZ3 0.0 
> 
> #Make a wrapper 
> wrapper <- function (ratingData, weight.func) { 
+ print(weight.func) #prove that the function is being passed 
+ ddply(ratingData, c('studentId','problem','part'), summarize, 
+   sum.weights = sum (weight.func(rating) )) 
+ } 
> wrapper(sampleData, weight.func=function(x) (x+.001)^-1 ) 
function(x) (x+.001)^-1 
Error in data.frame(sum.weights = sum(weight.func(rating))) : 
    could not find function "weight.func" 
> 
> #'globally' declare weight.func 
> weight.func <- function(x) (x+.001)^-1 
> wrapper(sampleData, weight.func=NULL ) 
NULL 
    studentId problem part sum.weights 
1  8001 problem26 partA 3002.495758 
2  8001 problem26 partB 8.983033 
3  8001 problem27 partA 4000.499750 
4  8001 problem27 partB 4000.999001 
5  8002 problem26 partA 2004.491766 
6  8002 problem26 partB 4000.499750 
7  8002 problem27 partA 5000.000000 
8  8002 problem27 partB 3000.999500 

La deuxième sortie est l'objectif. Toute aide appréciée! (Incluant une manière non plyr pour accomplir la même tâche.)

L'exemple ci-dessus est un exemple de jouet. C'est le cas le plus simple que je puisse avoir pour reproduire le comportement.

Répondre

2

vous pouvez utiliser ensemble:

w2 <- function(d, f){ 
    aggregate(rating~studentId+problem+part, function(x)sum(f(x)), data=d) 
} 

w2(sampleData, function(x) (x+.001)^-1 ) 

Notez que le nom de la colonne agrégée est déterminée automatiquement, donc si vous voulez nommer alors vous devez le faire par vous-même.

et vous pouvez même chose en ddply sans résumer

wrapper <- function (ratingData, weight.func) { 
    ddply(ratingData, c('studentId','problem','part'), function(x)c(sum.weights=sum(weight.func(x$rating)))) 
} 

wrapper(sampleData, weight.func=function(x) (x+.001)^-1 ) 

dans ce cas, vous pouvez spécifier le nom à l'intérieur fonction.

+0

Parfait, merci! –

+0

et vous pouvez même chose par ddply sans résumé. voir l'édition. – kohske

0

Je ne suis pas sûr que je change fait (prendre les espaces après « somme » ou de changer la valeur NULL à une fonction réelle ou < < quelque chose >>), mais cela fonctionne maintenant:

wrapper <- function (ratingData, weight.func=weight.func) { 
     ddply(ratingData, .variables=c('studentId','problem','part'), 
      .fun=summarise, sum.weights = sum(weight.func(rating) )) 
    } 

wrapper(sampleData, weight.func=weight.func ) 
    studentId problem part sum.weights 
1  8001 problem26 partA 3002.495758 
2  8001 problem26 partB 8.983033 
3  8001 problem27 partA 4000.499750 
4  8001 problem27 partB 4000.999001 
5  8002 problem26 partA 2004.491766 
6  8002 problem26 partB 4000.499750 
7  8002 problem27 partA 5000.000000 
8  8002 problem27 partB 3000.999500 
+0

Cela ne fonctionne pas pour moi. Puisque vous appelez: 'wrapper (sampleData, weight.func = weight.func)' cela signifie que weight.func est toujours en train de traîner en tant que global. Exemple: 'rm (weight.func); wrapper (sampleData, weight.func = fonction (x) (x + .001)^- 1) 'ne fonctionne pas. –

2

Ceci est un bug connu dans plyr: https://github.com/hadley/plyr/issues#issue/3

+1

Je ne pensais pas que plyr avait des bugs. Je pensais juste que je ne connaissais pas la bonne façon d'utiliser le logiciel. :) (Et vos paquets sont géniaux, btw.) –

0

Une mise à jour sur cette question dans plyr (https://github.com/hadley/plyr/issues/3):

Utilisez la fonction 'ici' dans plyr, il suffit de remplacer 'résumer', avec « ici (résumer) 'pour accéder à l'environnement où ddply a été appelé.

wrapper <- function(ratingData, weight.func){ 
      ddply(ratingData, c('studentId','problem','part'), 
       here(summarize), # here(summarize)! 
       sum.weights = sum(weight.func(rating)) 
       ) 
      } 
Questions connexes