2010-10-04 18 views
9

Czy istnieje sposób, aby można to poprawić, lub zrobić prostszą?sposób obliczania grupy według współczynnika

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

Pomysł jest taki sam jak oświadczenie SAS MEANS BY. Funkcja "oznacza.by" pobiera element data.frame i zmienną indeksującą i oblicza średnią w kolumnach elementu data.frame dla każdego zestawu wierszy odpowiadających unikatowym wartościom INDEX i zwraca nową ramkę danych za pomocą wiersza podaje unikalne wartości INDEKSU.

Jestem pewien, że musi istnieć lepszy sposób robienia tego w R, ale nie mogłem myśleć o niczym.

+0

Widziałem przykład, że pisał na swojej stronie. plyr został zaprojektowany dokładnie dla tej funkcji. Zaktualizowałem mój przykład, aby dopasować dane wyjściowe do Twojej witryny. –

Odpowiedz

13

Czy funkcja kruszywo robić to, co chcesz?

Jeśli nie, spójrz na pakiet plyr, daje kilka opcji do rozłożenia na części, wykonywania obliczeń na kawałkach, a następnie ponownego złożenia.

Możesz to również zrobić, korzystając z pakietu zmiany kształtu.

+0

tak agregat był tym, czego szukałem dziękuję. –

5

Chcesz tapply lub ave, w zależności od tego, jak chcesz, aby Twój wynik:

> 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

Żadne z nich nie zrobi tego, czego chcę, i zasadniczo jest to to samo. W rzeczywistości funkcja "przez", której używam, jest po prostu opakowaniem do aplikacji "tapply". Chodzi o to, że daję data.frame zastosować funkcję w kolumnach i uzyskać dane.frame lub matrycy z powrotem. –

+0

Moja zła. Mój przykład ma tylko jedną kolumnę. –

4

Z plyr

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

Aktualizacja:

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 jest inteligentny :)

Aktualizacja 2:

W odpowiedzi na Twój komentarz, wierzę i odlewane topienie z pakietu przekształcenia jest znacznie prostsze dla twojego celu.

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

Czy ta skala może się znajdować w data.frame ze 100 kolumnami? Zapisywanie danych.frame (x = średnie (x $ X), ...) jest niepraktyczne. Nie chcę być negatywny ani obraźliwy, ale taki jest kontekst mojej sytuacji, dlatego szukam najlepszego rozwiązania, które może się dobrze skalować. –

+0

Odpowiedź brzmi: tak, masz pełną funkcję do pracy z wewnątrz ddply. Jednak myślę, że odlewanie i topienie są bardziej wydajne w tym celu. Zaktualizowałem swoją odpowiedź. –

0

Używaj tylko funkcja rodzajowy w 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 
Powiązane problemy