2012-05-03 16 views
11

Probablemente sea una pregunta tonta, pero he leído el capítulo de Crawley sobre marcos de datos y he rastreado Internet y todavía no he podido hacer que funcione nada.Sumar filas basadas en combinaciones de factores específicos

Aquí está una muestra de datos similar a la mía:

> data<-data.frame(site=c("A","A","A","A","B","B"), plant=c("buttercup","buttercup", 
"buttercup","rose","buttercup","rose"), treatment=c(1,1,2,1,1,1), 
plant_numb=c(1,1,2,1,1,2), fruits=c(1,2,1,4,3,2),seeds=c(45,67,32,43,13,25)) 
> data 
    site  plant treatment plant_numb fruits seeds 
1 A buttercup   1   1  1 45 
2 A buttercup   1   1  2 67 
3 A buttercup   2   2  1 32 
4 A  rose   1   1  4 43 
5 B buttercup   1   1  3 13 
6 B  rose   1   2  2 25 

Lo que me gustaría hacer es crear un escenario en el que se suman "semillas" y "frutos" siempre sitio único & planta & tratamiento & combinaciones plant_numb existe. Idealmente, esto se traduciría en una reducción de filas, pero una preservación de las columnas originales (es decir, que necesito el ejemplo anterior para parecerse a esto :)

site  plant treatment plant_numb fruits seeds 
1 A buttercup   1   1  3 112 
2 A buttercup   2   2  1 32 
3 A  rose   1   1  4 43 
4 B buttercup   1   1  3 13 
5 B  rose   1   2  2 25 

Este ejemplo es bastante básico (mi conjunto de datos es de ~ 5000 filas), y aunque aquí solo se ven dos filas que se deben sumar, el número de filas que se deben sumar varía y varía de 1 a ~ 45.

He intentado con rowsum() y tapply() con resultados bastante desalentadores hasta el momento (los errores me dicen que estas funciones no son significativas para los factores), así que si incluso podría apuntarme en la dirección correcta, lo agradecería mucho!

Gracias tanto!

+0

vistazo a la 'plyr' y' data.table' tag. Muchas preguntas básicamente abordan esto. ¡Buena suerte! – Chase

+0

Vea también http://4dpiecharts.com/2011/12/16/a-quick-primer-on-split-apply-combine-problems/ –

Respuesta

11

Esperemos que el siguiente código se explique por sí mismo. Utiliza la función básica "agregado" y básicamente esto significa que para cada combinación única de sitio, planta, tratamiento y número de planta, observe la suma de las frutas y la suma de las semillas.

# Load your data 
data <- data.frame(site=c("A","A","A","A","B","B"), plant=c("buttercup","buttercup", 
"buttercup","rose","buttercup","rose"), treatment=c(1,1,2,1,1,1), 
plant_numb=c(1,1,2,1,1,2), fruits=c(1,2,1,4,3,2),seeds=c(45,67,32,43,13,25)) 

# Summarize your data 
aggregate(cbind(fruits, seeds) ~ 
     site + plant + treatment + plant_numb, 
     sum, 
     data = data) 
# site  plant treatment plant_numb fruits seeds 
#1 A buttercup   1   1  3 112 
#2 B buttercup   1   1  3 13 
#3 A  rose   1   1  4 43 
#4 B  rose   1   2  2 25 
#5 A buttercup   2   2  1 32 

El orden de las filas cambios (y lo resuelto por el sitio, planta, ...) pero es de esperar que no es demasiado de una preocupación.

Una forma alternativa de hacerlo sería usar ddply del paquete plyr.

library(plyr) 
ddply(data, .(site, plant, treatment, plant_numb), 
     summarize, 
     fruits = sum(fruits), 
     seeds = sum(seeds)) 
# site  plant treatment plant_numb fruits seeds 
#1 A buttercup   1   1  3 112 
#2 A buttercup   2   2  1 32 
#3 A  rose   1   1  4 43 
#4 B buttercup   1   1  3 13 
#5 B  rose   1   2  2 25 
+0

Impresionante - Estaba jugando con agregado después de hacer la pregunta, pero usted Me ha acelerado poderosamente. Gracias por tu ayuda. Sin embargo, una pregunta más: cuando ingreso el código como lo ha mostrado, aparece el error "Error en as.data.frame.default (x): no se puede forzar la clase" fórmula "en un data.frame" . Alguna idea para hacer que funcione? – user1371443

+0

Ambos, desafortunadamente. Recibo el mismo mensaje de error para el ejemplo y mis conjuntos de datos reales (sin espacios):> aggregate (cbind (fruits, seeds) ~ site + plant + treatment + plant_numb, sum, data = data) Error en como .data.frame.default (x): no se puede forzar la "fórmula" de clase en un data.frame – user1371443

+0

La solución plyr debería funcionar, supongo. Pero parece que no tienes una versión de fórmula de agregado. ¿Qué versión de R estás usando? Creo que agregado ha permitido la entrada de fórmulas desde 2.11 – Dason

4

Y para completar, aquí está la solución data.table, según lo sugerido por @Chase. Para grandes conjuntos de datos éste será probablemente el método más rápido:

library(data.table) 
data.dt <- data.table(data) 
setkey(data.dt, site) 
data.dt[, lapply(.SD, sum), by = list(site, plant, treatment, plant_numb)] 

    site  plant treatment plant_numb fruits seeds 
[1,] A buttercup   1   1  3 112 
[2,] A buttercup   2   2  1 32 
[3,] A  rose   1   1  4 43 
[4,] B buttercup   1   1  3 13 
[5,] B  rose   1   2  2 25 

La parte lapply(.SD, sum) resume todas las columnas que no son parte del conjunto de agrupación (. Es decir, las columnas no en el by función)

Cuestiones relacionadas