2012-07-30 13 views
9

Tengo un marco de datos de sitios de aminoácidos, y quiero crear un nuevo marco de datos de cada combinación por pares de estos sitios.Pegar juntos cada par de columnas en un marco de datos en R?

Los datos originales se verá algo como esto:

df<-cbind(letters[1:5], letters[6:10], letters[11:15]) 
df 
[,1] [,2] [,3] 
[1,] "a" "f" "k" 
[2,] "b" "g" "l" 
[3,] "c" "h" "m" 
[4,] "d" "i" "n" 
[5,] "e" "j" "o" 

Y lo que me gustaría es la siguiente:

newdf<-cbind(paste(df[,1],df[,2],sep=""),paste(df[,1],df[,3],sep=""),(paste(df[,2],df[,3],sep=""))) 
newdf 
    [,1] [,2] [,3] 
[1,] "af" "ak" "fk" 
[2,] "bg" "bl" "gl" 
[3,] "ch" "cm" "hm" 
[4,] "di" "dn" "in" 
[5,] "ej" "eo" "jo" 

Los datos reales pueden tener cientos de filas y/o columnas, por lo que, obviamente, Necesito una forma menos manual de hacer esto. Cualquier ayuda es muy apreciada, no soy más que un biólogo humilde y mi conjunto de habilidades en esta área es bastante limitado.

+0

¿Desea solo pares en el mismo orden que su marco de datos? Es decir, ¿por qué no es "fa" o "ka" en su primera fila? –

+0

Gracias, el orden no es importante en términos de identidad, es decir, "fa" = "af", pero sí, los pares deben estar en el mismo orden que el marco de datos, como en el ejemplo –

Respuesta

12

Una combinación de combn() y apply() le conseguirá todas las combinaciones de pares no ordenados:

df <- cbind(letters[1:5], letters[6:10], letters[11:15]) 

apply(X = combn(seq_len(ncol(df)), 2), 
     MAR = 2, 
     FUN = function(jj) { 
      apply(df[, jj], 1, paste, collapse="") 
     }  
) 
#  [,1] [,2] [,3] 
# [1,] "af" "ak" "fk" 
# [2,] "bg" "bl" "gl" 
# [3,] "ch" "cm" "hm" 
# [4,] "di" "dn" "in" 
# [5,] "ej" "eo" "jo" 

(Si lo que está pasando en el anterior no es claro de inmediato, es posible que desee echar un vistazo rápido a el objeto devuelto por combn(seq_len(ncol(df)), 2). sus columnas enumerar todos los combos de los enteros pares no ordenados entre 1 y n, donde n es el número de columnas de la trama de datos.)

+0

+1 Apenas superado yo a eso! Deleted mine –

+0

Muchas gracias --- esto es exactamente lo que necesitaba. ¿Por qué no publiqué esta pregunta hace cinco horas? Todos ustedes son geniales. –

9

Usted puede utilizar el argumento FUN al combn para pegar juntas las columnas de cada combinación:

combn(ncol(df),2,FUN=function(i) apply(df[,i],1,paste0,collapse="")) 
+1

+1 Dulce, y dulcemente ofuscado para arrancar! –

+0

@ JoshO'Brien: ¿qué está ofuscado al respecto? El 'FUN' arg a' combn' puede parecer un poco extraño, pero es muy útil si hay muchas combinaciones porque no tienes que almacenarlas todas en un objeto intermedio. –

+1

@otherJosh - Ofuscado fue probablemente la palabra incorrecta. 'Compacto' hubiera sido mejor. Como yo mismo fui un "biólogo humilde", solo estaba consciente de lo difícil que es analizar esto (y mi respuesta para el caso). (Para que quede claro, todavía soy un biólogo, simplemente ya no es un humilde ...;) –

2

Josh y respuestas de Joshua son mejores, pero pensé que me daría mi enfoque:

Esto requiere la descarga de qdap varsion 1.1.0 usando la función paste2:

library(qdap) 

ind <- unique(t(apply(expand.grid(1:3, 1:3), 1, sort))) 
ind <- ind[ind[, 1] != ind[, 2], ] 
sapply(1:nrow(ind), function(i) paste2(df[, unlist(ind[i, ])], sep="")) 

Aunque robar de sus respuestas esto sería mucho más legible:

ind <- t(combn(seq_len(ncol(df)), 2)) 
sapply(1:nrow(ind), function(i) paste2(df[, unlist(ind[i, ])], sep="")) 
-1

Recuerde que usted recibirá una gran cantidad de columnas en su nuevo hoja.de.datos, teniendo en cuenta que usted dice que tiene cientos de columnas en el hoja.de.datos originales: si los datos originales contienen n columnas, entonces el nuevo uno contendrá columnas n (n-1)/2 - esto escala cuadráticamente.

+3

Esto no es una respuesta; debe agregar esto como un comentario a la pregunta. –

+0

Traté de cambiar esto a un comentario. Sin embargo, con la poca reputación que tengo, parece que aún no puedo comentar las preguntas. ¿Tendría sentido para otra persona convertir esto en un comentario, o cruzaría la línea para enviar correo no deseado? –

Cuestiones relacionadas