2017-05-14 2 views
1

J'ai rencontré un problème étrange où une fonction d'agrégat agit bizarrement si je l'appelle en fonction personnalisée. Il semble que la fonction de sous-ensemble soit totalement dépassée:créer une fonction et un sous-ensemble de trame de données ne fonctionne pas dans la fonction d'agrégat

Pour vous donner une idée du problème, je vais le décomposer en deux parties. 1. sans fonction personnalisée

c<- data.frame(A = c("carr","bike","truck","carr","truck","bike","bike","carr","truck","carr","truck","truck","carr","truck","truck"), 
       B = c(10,20,30,23,45,56,78,44,10,20,30,10,20,30,67), 
       D = c(1,2,3,1,2,3,2,3,2,3,2,2,3,2,1)) 

c_subset<- subset(c,(A=="carr")|(A=="bike")) 

dg<- aggregate(B ~ D + A ,c_subset,max) 

la valeur de dG:

D A B   
2 bike 78 
3 bike 56 
1 carr 23 
3 carr 44 

Quelle est exactement la façon dont il devrait être.

Mais 2. Avec la fonction personnalisée:

rtk <- function(datam,inc_coll,inc_vall,lb,ld){ 
    datam_subset <- subset(c,inc_coll %in% inc_vall) 
    dg1<- aggregate(lb ~ ld + inc_coll,datam_subset,max) 

    return(dg1) 
} 

c_ans <- rtk(c,c$A,c("carr","bike"),c$B,c$D) 

La réponse est:

ld inc_coll lb 

2 bike 78 
3 bike 56 
1 carr 23 
3 carr 44 
1 truck 67 
2 truck 45 
3 truck 30 

Maintenant, je veux savoir pourquoi il devient "camion" en fonction d'agrégation? Bien que dans la fonction agrégée j'ai utilisé des données datam_subset qui a été un sous-ensemble et contient uniquement des données sur "carr" et "vélo".

Peut-être qu'il me manque quelque chose de très basique. Sera reconnaissant pour votre aide. Merci

+1

vous donnez en entrée à votre fonction 'rtk' les colonnes réelles de votre datafra d'origine moi au lieu de simplement les noms de colonnes.Donc, le 'subset' fonctionne, mais le' aggregate' est fait sur les colonnes de 'c'. – Lamia

+1

comme personne ne l'a vraiment mentionné. http://stackoverflow.com/questions/9860090/why-is-better-than-subset donne quelques réflexions sur l'utilisation du sous-ensemble dans une fonction. Aussi l'agrégat a un argument de sous-ensemble qui peut rendre les choses plus faciles – user20650

+0

* datam * param n'est jamais utilisé dans la fonction même si vous passez 'c'into – Parfait

Répondre

0

Passer les noms de colonnes à une fonction est une question souvent posée comme il peut être contre-intuitif. Cochez cette question: Pass a data.frame column name to a function Une meilleure façon d'écrire votre fonction serait de passer à TKP les noms de colonnes au lieu des colonnes elles-mêmes et les utiliser pour ce que vous voulez faire:

rtk <- function(datam,inc_coll,inc_vall,lb,ld){ 
## Access the column using df[[colname]] to do the subset 
    datam_subset <- subset(c,c[[inc_coll]] %in% inc_vall); 
## Define the formula you will use in the aggregate function 
f=as.formula(paste0(lb,"~",ld,"+", inc_coll)) 
## Perform the aggregation 
    dg1<- aggregate(f,datam_subset,max); 
    return(dg1) 
} 

Ensuite, appelez à l'aide appropriée les noms de colonnes:

c_ans <- rtk(c,"A",c("carr","bike"),"B","D") 

qui vous donne:

D A B 
1 2 bike 78 
2 3 bike 56 
3 1 carr 23 
4 3 carr 44 
+0

Merci Lamia pour l'expliquer en détail. La solution @Yannis fonctionne également mais la vôtre est plus configurable. –

0

Il est parce que vous appelez fonction d'agrégat est de deux data.frames

Ce:

dg1<- aggregate(lb ~ ld + inc_coll, datam_subset, max) 

lit réellement comme:

dg1<- aggregate(c$B ~ c$D + c$A, datam_subset, max) 

si vous surchargez l'appel et datam_subset il suffit d'appeler c.

0

Actuellement, il y a 2 problèmes. Tout d'abord, vous sous-définissez c pas datam comme d'autres l'ont souligné, mais encore une fois cela ne résout pas le problème. datam_subset n'a pas de colonnes nommées lb, ld, inc_call. Donc, votre fonction devrait ressembler à:

rtk <- function(datam, inc_coll, inc_vall, lb, ld){ 
    datam_subset <- subset(datam, inc_coll %in% inc_vall) 
    names(datam_subset)<- c("inc_coll", "lb", "ld") 
    dg1<- aggregate(lb ~ ld + inc_coll,datam_subset,max) 
    return(dg1) 
} 

> c_ans <- rtk(c,c$A,c("carr","bike"),c$B, c$D) 
> c_ans 
    ld inc_coll lb 
1 2  bike 78 
2 3  bike 56 
3 1  carr 23 
4 3  carr 44 

Vous pouvez changer les noms à c_ans juste en colnames(c_ans)<- c("D", "A", "B")