2011-05-09 36 views
5

Tengo un marco de datos donde algunas columnas consecutivas tienen el mismo nombre. Necesito buscarlos, agregar sus valores para cada fila, soltar una columna y reemplazar la otra con su suma. sin saber previamente qué patrones están duplicados, posiblemente teniendo que comparar un nombre de columna con el siguiente para ver si hay una coincidencia.¿cómo busco columnas con el mismo nombre, agrego los valores de columna y reemplazo estas columnas con el mismo nombre por su suma? Uso de R

¿Alguien puede ayudar?

Gracias de antemano.

Respuesta

2

Algunos datos de muestra.

dfr <- data.frame(
    foo = rnorm(20), 
    bar = 1:20, 
    bar = runif(20), 
    check.names = FALSE 
) 

Método: Desplácese sobre los nombres de columna únicos; si solo hay uno de ese nombre, entonces seleccionar todas las columnas con ese nme devolverá un vector, pero si hay duplicados también será un marco de datos. Use rowSums para sumar las filas. ( Duh. EDITAR: No es tan 'duh' como se pensaba anteriormente) lapply devuelve una lista, que tenemos que reformar en un marco de datos, y finalmente corregimos los nombres. EDITAR: sapply evita la necesidad del último paso.

unique_col_names <- unique(colnames(dfr)) 
new_dfr <- sapply(unique_col_names, function(name) 
{ 
    subs <- dfr[, colnames(dfr) == name] 
    if(is.data.frame(subs)) 
    rowSums(subs) 
    else 
    subs 
}) 
+0

En cuanto a la 'Duh': de hecho rowSums suma sobre las filas, pero suma rowsum sobre columnas ;-) – Tommy

+0

@Tommy: Buen punto. –

+0

gracias por la respuesta. Trabajé con los rowSums "Duh", ese no era el problema principal de mi problema. Además, si puedo decirlo, pensé que "Duh" no era una "función" adecuada para publicar en este foro !;) – Assu

7
> dfrm <- data.frame(a = 1:10, b= 1:10, cc= 1:10, dd=1:10, ee=1:10) 
> names(dfrm) <- c("a", "a", "b", "b", "b") 
> sapply(unique(names(dfrm)[duplicated(names(dfrm))]), 
     function(x) Reduce("+", dfrm[ , grep(x, names(dfrm))])) 
     a b 
[1,] 2 3 
[2,] 4 6 
[3,] 6 9 
[4,] 8 12 
[5,] 10 15 
[6,] 12 18 
[7,] 14 21 
[8,] 16 24 
[9,] 18 27 
[10,] 20 30 

EDIT 2: Uso de rowSums permite la simplificación de la primera argumentto sapply simplemente unique(names(dfrm)) a costa de tener que recordar incluir gota = FALSO en "[":

sapply(unique(names(dfrm)), 
     function(x) rowSums(dfrm[ , grep(x, names(dfrm)), drop=FALSE])) 

Para hacer frente con NA's:

sapply(unique(names(dfrm)), 
     function(x) apply(dfrm[grep(x, names(dfrm))], 1, 
       function(y) if (all(is.na(y))) {NA} else { sum(y, na.rm=TRUE) } 
     )    ) 

(Editar nota: se dirigió Tommy contra-ejemplo al poner unique alrededor la construcción de los nombres (.) [.]. El código erróneo era:

sapply(names(dfrm)[unique(duplicated(names(dfrm)))], 
    function(x) Reduce("+", dfrm[ , grep(x, names(dfrm))])) 
+1

No funciona en 'dfrm = data.frame (a = 1: 10, b = 20:29, a = 101: 110, b = 200: 209, a = 1001: 1010, check.names = F) ' – Tommy

+0

@Tommy. Gracias. Señala que debería haber envuelto los únicos nombres (dfrm) [duplicados ...] corregidos. –

+0

+1 Lindo uso de 'Reducir'. –

1

Una forma es identificar duplcates usando (sorpresa) la función duplicated, y luego bucle a través de ellos para calcular las sumas. He aquí un ejemplo:

dat.dup <- data.frame(x=1:10, x=1:10, x=1:10, y=1:10, y=1:10, z=1:10, check.names=FALSE) 
dups <- unique(names(dat.dup)[duplicated(names(dat.dup))]) 
for (i in dups) { 
dat.dup[[i]] <- rowSums(dat.dup[names(dat.dup) == i]) 
} 
dat <- dat.dup[!duplicated(names(dat.dup))] 
+0

gracias, fue mi idea original pero no pude codificarla. Y tampoco estaba familiarizado con "único". – Assu

4

Aquí está mi un trazador de líneas

# transpose data frame, sum by group = rowname, transpose back. 
t(rowsum(t(dfrm), group = rownames(t(dfrm)))) 
+0

+1.Muy claro, aunque vale la pena señalar que, tal como está escrito, necesitaría 'as.data.frame()' si eso es lo que se quiere. – Henry

+0

@Henry. Sí. Sería fácil manipular esta salida en cualquier formato que desee el OP. Como usa 'rowsum' que llama a una función C, es rápido y se ejecuta 1.5 veces más rápido en el conjunto de datos de ejemplo. Sospecho que sería aún más rápido en un marco de datos más grande. – Ramnath

Cuestiones relacionadas