2012-06-09 14 views
5

Tengo un data.frame con 1,000 filas y 3 columnas. Contiene una gran cantidad de duplicados y he utilizado plyr para combinar las filas duplicadas y agregar un recuento para cada combinación como se explica en this thread.Busque y combine filas duplicadas en un data.frame pero ignore el orden de las columnas

He aquí un ejemplo de lo que tengo ahora (todavía tengo también la hoja.de.datos original con todos los duplicados si tengo que empezar desde allí):

name1 name2 name3  total 
1 Bob  Fred  Sam  30 
2 Bob  Joe  Frank  20 
3 Frank Sam  Tom  25 
4 Sam  Tom  Frank  10 
5 Fred  Bob  Sam  15 

Sin embargo, orden de las columnas no lo hace importar. Solo quiero saber cuántas filas tienen las mismas tres entradas, en cualquier orden. ¿Cómo puedo combinar las filas que contienen las mismas entradas, ignorando el orden? En este ejemplo, quisiera combinar las filas 1 y 5, y las filas 3 y 4.

Respuesta

4

Defina otra columna que sea una "pasta clasificada" de los nombres, que tendría el mismo valor de "Bob ~ Fred ~ Sam" para las filas 1 y 5. Luego agregue basado en eso.

Breve fragmento de código (supone que el marco de datos original es dd): todo es realmente intuitivo. Creamos una columna lookup (echar un vistazo y deben explicarse por sí misma), obtener las sumas de la columna de la total para cada combinación, y luego filtrar a las combinaciones únicas ...

dd$lookup=apply(dd[,c("name1","name2","name3")],1, 
            function(x){paste(sort(x),collapse="~")}) 
tab1=tapply(dd$total,dd$lookup,sum) 
ee=dd[match(unique(dd$lookup),dd$lookup),] 
ee$newtotal=as.numeric(tab1)[match(ee$lookup,names(tab1))] 

Ahora tiene en ee un conjunto de filas únicas y sus recuentos totales correspondientes. Fácil, y no se necesitan paquetes externos. Y, lo más importante, ¡puedes ver en cada etapa del proceso lo que está sucediendo!

(actualización menor para ayudar OP :) Y si quieres una versión limpia en marcha de la respuesta final:

outdf = with(ee,data.frame(name1,name2,name3, 
          total=newtotal,stringsAsFactors=FALSE)) 

Esto le da una trama de datos ordenada con las tres columnas de nombre de suma importancia, y con los totales agregados en una columna llamada total en lugar de newtotal.

+0

Esto también funcionó (después de eliminar espacios de las entradas de data.frame). También elimina el paso de copiar/pegar datos manualmente. Sin embargo, esto me deja con: 'nombre1 nombre2 nombre3 de búsqueda total de newtotal' 1 Bob Fred Sam 30 Bob ~ ~ Fred Sam 45 2 Bob Joe Frank 20 Bob ~ ~ Frank Joe 20 3 Frank Sam Tom Frank 25 ~ Sam ~ Tom 35' – jdfinch3

+0

Hmmm, no se puede obtener el bloque de código para trabajar en los comentarios ... sin embargo, ee muestra los resultados combinados sin los totales actualizados y luego junto a los resultados combinados con los totales actualizados (y con ~ reemplazo las pestañas entre las entradas de fila). Estoy seguro de que esta es una solución fácil, pero no sé lo suficiente R (aún) para arreglarlo fácilmente ... – jdfinch3

+0

De acuerdo, en realidad tomé el tiempo para leer su código y pensar cada acción y me di cuenta de que la respuesta a mi pregunta era aún más obvia de lo que había pensado. Acabo de tomar las dos nuevas columnas y las inserté en un nuevo data.frame (y reemplacé el "~" con "" solo para que sea más fácil de leer). ¡Gracias! – jdfinch3

4

Ordenar el índice de columnas, a continuación, utilizar ddply para agregar y suma:

definir los datos:

dat <- " name1 name2 name3  total 
1 Bob  Fred  Sam  30 
2 Bob  Joe  Frank  20 
3 Frank Sam  Tom  25 
4 Sam  Tom  Frank  10 
5 Fred  Bob  Sam  15" 

x <- read.table(text=dat, header=TRUE) 

Crear una copia:

xx <- x 

Uso apply para ordenar las columnas, luego agregar:

xx[, -4] <- t(apply(xx[, -4], 1, sort)) 
library(plyr) 
ddply(xx, .(name1, name2, name3), numcolwise(sum)) 
    name1 name2 name3 total 
1 Bob Frank Joe 20 
2 Bob Fred Sam 45 
3 Frank Sam Tom 35 
+0

¿No lo ha hecho de esta manera ha cambiado los datos originales? La primera línea solía decir "Bob, Fred, Sam" ...? –

+1

@timp Sí, pero como OP dijo que el pedido no importa, probablemente eso no importe. De todos modos, los datos originales todavía están en 'x'. Es por eso que creé un nuevo objeto 'xx'. Pero la razón por la cual el orden de fila es diferente es porque 'ddply' ordena las variables de agrupación antes de hacer la agregación. – Andrie

+1

Eek! Es por eso que tiendo a alejarme de estos paquetes nuevos: siempre encuentro que realmente debes conocerlos de otra manera, puedes quemarte fácilmente. Por otra parte, supongo que a veces no te molestaría que tus filas se reordenan (aunque eso sería una pesadilla para el tipo de cosas para las que utilizo R). Gracias por los consejos :) –

Cuestiones relacionadas