2012-04-16 46 views
27

Tengo un marco de datos donde una columna es nombres de especies, y la segunda columna es valores de abundancia. Debido al procedimiento de muestreo, algunas especies aparecen más de una vez (es decir, hay más de una fila con la Especie X en ella). Me gustaría consolidar esas entradas y sumar sus abundancias.Consolidar filas duplicadas

Por ejemplo, dada esta trama de datos:

set.seed(6) 
df=data.frame(
    x=c("sp1","sp2","sp3","sp3","sp4","sp2","sp3"), 
    y=rpois(7,2)); df 

que produce:

x y 
1 sp1 2 
2 sp2 4 
3 sp3 1 
4 sp3 1 
5 sp4 3 
6 sp2 5 
7 sp3 5 

Me gustaría en vez producen:

x y 
1 sp1 2  
2 sp2 9  (5+4) 
3 sp3 7  (5+1+1) 
5 sp4 3 

Gracias de antemano por cualquier ayuda que ¡puede proporcionar!

Respuesta

35

Esto funciona:

library(plyr) 
ddply(df,"x",numcolwise(sum)) 

en palabras: (1) dividir la trama de datos df por la columna de "x"; (2) para cada fragmento, tome la suma de cada columna de valores numéricos; (3) vuelva a colocar los resultados en un solo marco de datos. (dd en ddply significa "tener un d marco ata como entrada, devolver un d marco ata")

Otro, posiblemente más clara, enfoque:

aggregate(y~x,data=df,FUN=sum) 

Ver quick/elegant way to construct mean/variance summary table para un relacionado (un poco más complejo) pregunta.

+0

D'oh! ¿Cómo pasó esta aplicación de libro de texto de ddply ... Gracias Ben! – jslefche

+0

+1 para la aplicación de numcolwise y suma. Estuve dando vueltas con Transformar y mutar tratando de hacer que esto funcione exactamente. –

+1

AFAIK, "aggregate (y ~ x + z, data = df, FUN = sum)" se podría usar para conservar una columna * adicional * (aquí "z"), si existiera la necesidad (era la necesidad en mi caso)Por favor corrígeme si estoy equivocado. – Shadow

20

simple como aggregate:

aggregate(df['y'], by=df['x'], sum) 
6
> tapply(df$y, df$x, sum) 
sp1 sp2 sp3 sp4 
    2 9 7 3 

si tiene que ser la respuesta de un data.frame de Ben funciona muy bien. o puede forzar la salida de tapply.

out <- tapply(df$y, df$x, sum) 
>  data.frame(x=names(out), y=out, row.names=NULL) 
    x y 
1 sp1 2 
2 sp2 9 
3 sp3 7 
4 sp4 3 
8

Una solución data.table de tiempo y eficiencia de la memoria

library(data.table) 
DT <- as.data.table(df) 
# which columns are numeric 
numeric_cols <- which(sapply(DT, is.numeric)) 
DT[, lapply(.SD, sum), by = x, .SDcols = numeric_cols] 

O, en su caso, dado que usted sabe que no es sólo la columna y 1 desea suma sobre

DT[, list(y=sum(y)),by=x] 
1

Un MWE para verificar si una fórmula para respetar una segunda variable (es decir, aquí "Z" y además de "X", realmente funcionaría:

example = data.frame(X=c("x"),Z=c("a"),Y=c(1), stringsAsFactors=F) 
newrow = c("y","b",1) 
example <- rbind(example, newrow) 
newrow = c("z","a",0.5) 
example <- rbind(example, newrow) 
newrow = c("x","b",1) 
example <- rbind(example, newrow) 
newrow = c("x","b",2) 
example <- rbind(example, newrow) 
newrow = c("y","b",10) 
example <- rbind(example, newrow) 
example$X = as.factor(example$X) 
example$Z = as.factor(example$Z) 
example$Y = as.numeric(example$Y) 
example_agg <- aggregate(Y~X+Z,data=example,FUN=sum) 
6

Una solución dplyr:

library(dplyr) 
df %>% group_by(x) %>% summarise(y = sum(y)) 
Cuestiones relacionadas