2010-10-04 5 views
9

¿Hay alguna manera de que esto se pueda mejorar, o hacer de forma más simple?medio de cálculo de un grupo por factor

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

La idea es la misma que una declaración de SAS MEANS BY. La función 'means.by' toma un data.frame y una variable de indexación y calcula la media sobre las columnas del data.frame para cada conjunto de filas correspondientes a los valores únicos de INDEX y devuelve un nuevo marco de datos con la fila nombra los valores únicos de INDEX.

Estoy seguro de que debe haber una forma mejor de hacerlo en R, pero no se me ocurrió nada.

+0

vi el ejemplo que usted envió en su sitio. plyr está diseñado exactamente para esta funcionalidad. Actualicé mi ejemplo para que coincida con el resultado en su sitio. –

Respuesta

13

hace la función de agregado lo que quiere?

Si no, mire el paquete plyr, le da varias opciones para desmontar cosas, hacer cálculos en las piezas y luego volver a armarlas.

También puede hacer esto con el paquete de remodelación.

+0

yes aggregate era lo que estaba buscando gracias. –

5

¿Quieres tapply o ave, dependiendo de cómo desea que su salida:

> 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

Ninguno de esos hará lo que yo quiera, y son esencialmente lo mismo. De hecho, la función "por" que estoy usando es simplemente una envoltura para tapply. La idea es dar un data.frame aplicar una función sobre las columnas y recuperar un data.frame o matrix. –

+0

Mi mal. Mi ejemplo solo tiene una columna. –

4

Con plyr

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

Actualización:

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

Sede, plyr es inteligente :)

Actualización 2:

En respuesta a tu comentario, creo fundido y derretir desde el paquete de remodelación son mucho más simples para su propósito.

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

¿Se puede escalar esto a un data.frame con 100 columnas? Escribir data.frame (x = mean (x $ X), ...) no es práctico. No pretendo ser negativo o despectivo, pero ese es el contexto de mi situación, por lo que busco la mejor solución que pueda escalar bien. –

+0

La respuesta es sí, tiene una función completa para trabajar dentro de ddply. Sin embargo, creo que el molde y el derretimiento son más eficientes para este propósito. He actualizado mi respuesta. –

0

Usar sólo la función genérica en 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 
Cuestiones relacionadas