2010-10-04 11 views
9

Existe-t-il un moyen de l'améliorer ou de le rendre plus simple?moyens de calcul d'un groupe par facteur

means.by<-function(data,INDEX){ 
    b<-by(data,INDEX,function(d)apply(d,2,mean)) 
    return(structure(
    t(matrix(unlist(b),nrow=length(b[[1]]))), 
     dimnames=list(names(b),col.names=names(b[[1]])) 
)) 
} 

L'idée est la même que pour une instruction SAS MEANS BY. La fonction 'means.by' prend un data.frame et une variable d'indexation et calcule la moyenne sur les colonnes du data.frame pour chaque ensemble de lignes correspondant aux valeurs uniques d'INDEX et renvoie une nouvelle trame de données avec la ligne nomme les valeurs uniques de INDEX.

Je suis sûr qu'il doit y avoir une meilleure façon de le faire dans R mais je ne pouvais penser à rien.

+0

j'ai vu l'exemple que vous avez publié sur votre site. plyr est conçu exactement pour cette fonctionnalité. J'ai mis à jour mon exemple pour correspondre à la sortie sur votre site. –

Répondre

13

Est-ce que la fonction regroupez-ce que vous voulez? Si ce n'est pas le cas, regardez le paquet plyr, il donne plusieurs options pour démonter, faire des calculs sur les pièces, puis le remettre ensemble.

Vous pouvez également faire cela en utilisant le paquet reshape.

+0

oui agrégat était ce que je cherchais merci. –

5

Vous voulez tapply ou ave, selon la façon dont vous voulez que votre sortie:

> Data <- data.frame(grp=sample(letters[1:3],20,TRUE),x=rnorm(20)) 
> ave(Data$x, Data$grp) 
[1] -0.3258590 -0.5009832 -0.5009832 -0.2136670 -0.3258590 -0.5009832 
[7] -0.3258590 -0.2136670 -0.3258590 -0.2136670 -0.3258590 -0.3258590 
[13] -0.3258590 -0.5009832 -0.2136670 -0.5009832 -0.3258590 -0.2136670 
[19] -0.5009832 -0.2136670 
> tapply(Data$x, Data$grp, mean) 
     a   b   c 
-0.5009832 -0.2136670 -0.3258590 

# Example with more than one column: 
> Data <- data.frame(grp=sample(letters[1:3],20,TRUE),x=rnorm(20),y=runif(20)) 
> do.call(rbind,lapply(split(Data[,-1], Data[,1]), mean)) 
      x   y 
a -0.675195494 0.4772696 
b 0.270891403 0.5091359 
c 0.002756666 0.4053922 
+0

Ni l'un ni l'autre ne fera ce que je veux, et c'est essentiellement la même chose. En fait, la fonction «par» que j'utilise est simplement un emballage pour tapply. L'idée est que je donne un data.frame appliquez une fonction sur les colonnes et récupérez un data.frame ou une matrice. –

+0

Mon mauvais. Mon exemple n'a qu'une seule colonne. –

4

Avec plyr

library(plyr) 
df <- ddply(x, .(id),function(x) data.frame(
mean=mean(x$var) 
)) 
print(df) 

Mise à jour:

data<-data.frame(I=as.factor(rep(letters[1:10],each=3)),x=rnorm(30),y=rbinom(30,5,.5)) 
ddply(data,.(I), function(x) data.frame(x=mean(x$x), y=mean(x$y))) 

Voir, plyr est intelligent :)

Mise à jour 2:

En réponse à votre commentaire, je crois jeter et fondre du paquet remodeler sont beaucoup plus simples pour votre but.

cast(melt(data),I ~ variable, mean) 
+0

Cette échelle peut-elle être un data.frame avec 100 colonnes? Ecrire data.frame (x = mean (x $ X), ...) n'est pas pratique. Je ne veux pas être négatif ou désobligeant, mais c'est le contexte de ma situation et je cherche donc la meilleure solution qui puisse bien évoluer. –

+0

La réponse est oui, vous avez toute une fonction pour travailler avec ddply. Cependant, je pense que la fonte et la fonte sont plus efficaces à cette fin. J'ai mis à jour ma réponse. –

0

Utilisez uniquement la fonction générique R.

>d=data.frame(type=as.factor(rep(c("A","B","C"),each=3)), 
x=rnorm(9),y=rgamma(9,2,1)) 
> d 
type   x   y 
1 A -1.18077326 3.1428680 
2 A -0.91930418 4.4606603 
3 A 0.88345422 1.0979301 
4 B 0.06964133 1.1429911 
5 B -1.15380345 2.7609049 
6 B 1.13637202 0.6668986 
7 C -1.12052765 1.7352306 
8 C -1.34803630 2.3099202 
9 C -2.23135374 0.7244689 
> 
> cbind(lm(x~-1+type,data=d)$coef,lm(y~-1+type,data=d)$coef) 
     [,1]  [,2] 
typeA -0.4055411 2.900486 
typeB 0.0174033 1.523598 
typeC -1.5666392 1.589873