2010-10-04 8 views
9

Gibt es eine Möglichkeit, dass dies verbessert werden kann, oder einfacher?berechnen Sie mit einer Gruppe von Faktor

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]])) 
)) 
} 

Die Idee ist die gleiche wie eine SAS MEANS BY-Anweisung. Die Funktion 'means.by' verwendet einen data.frame und eine Indexvariable und berechnet den Mittelwert über die Spalten des dat.frames für jeden Zeilensatz, der den eindeutigen Werten von INDEX entspricht, und gibt einen neuen Datenrahmen mit der Zeile zurück Benennt die eindeutigen Werte von INDEX.

Ich bin mir sicher, dass es einen besseren Weg geben muss, dies in R zu tun, aber mir fällt nichts ein.

+0

sah ich das Beispiel, das Sie auf Ihrer Website veröffentlicht. plyr ist genau auf diese Funktionalität ausgelegt. Ich habe mein Beispiel aktualisiert, damit es mit der Ausgabe auf Ihrer Website übereinstimmt. –

Antwort

13

Ist die Aggregatfunktion tun, was Sie?

Wenn nicht, schauen Sie sich das Plyr-Paket an, es gibt mehrere Möglichkeiten, Dinge auseinander zu nehmen, Berechnungen an den Teilen durchzuführen und sie dann wieder zusammenzusetzen.

Sie können dies möglicherweise auch mithilfe des Umformpakets tun.

+0

ja Aggregat war was ich gesucht habe danke. –

5

Sie wollen tapply oder ave, je nachdem, wie Sie Ihre Ausgabe wollen: wollen

> 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

Keiner von denen wird tun, was ich will, und sind im Wesentlichen das Gleiche. Tatsächlich ist die Funktion "by", die ich benutze, einfach ein Wrapper für tapply. Die Idee ist, dass ich einem data.frame eine Funktion über die Spalten anlege und einen dat.frame oder eine Matrix zurückbekomme. –

+0

Mein schlechtes. Mein Beispiel hat nur eine Spalte. –

4

Mit plyr

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

Update:

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))) 

See, plyr smart :)

Update 2:

Als Antwort auf Ihren Kommentar, ich glaube, gegossen und schmelzen aus dem Umformpaket sind viel einfacher für Ihren Zweck.

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

Kann dies auf einen Datenrahmen mit 100 Spalten skaliert werden? Das Schreiben von data.frame (x = Mittelwert (x $ X), ...) ist nicht praktisch. Ich möchte nicht negativ oder abwertend sein, aber das ist der Kontext meiner Situation und ich suche nach der besten Lösung, die gut skalieren kann. –

+0

Die Antwort ist ja, Sie haben eine ganze Funktion innerhalb von ddply zu arbeiten. Ich denke jedoch, dass Gießen und Schmelzen für diesen Zweck effizienter sind. Ich habe meine Antwort aktualisiert. –

0

Verwenden Sie nur die generische Funktion in 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 
Verwandte Themen