two que hace funcion dataframes data concatenate r join statistics bind do.call

que - merge rows in r



Usando cbind en una lista arbitrariamente larga de objetos (4)

La función do.call es muy útil aquí:

A <- 1:10 B <- 11:20 C <- 20:11 > do.call(cbind, list(A,B,C)) [,1] [,2] [,3] [1,] 1 11 20 [2,] 2 12 19 [3,] 3 13 18 [4,] 4 14 17 [5,] 5 15 16 [6,] 6 16 15 [7,] 7 17 14 [8,] 8 18 13 [9,] 9 19 12 [10,] 10 20 11

Me gustaría encontrar una forma de crear un data.frame usando cbind() para unir muchos objetos separados. Por ejemplo, si A, B, C y D son todos vectores de igual longitud, uno puede crear data.frame ABCD con

ABCD <- cbind(A,B,C,D)

Sin embargo, cuando la cantidad de objetos que se combinarán aumenta, es tedioso escribir todos sus nombres. Además, ¿hay alguna manera de llamar a cbind() en un vector de nombres de objetos, por ejemplo,

objs <- c("A", "B", "C", "D") ABCD <- cbind(objs)

o en una lista que contiene todos los objetos a combinar, por ejemplo

obj.list <- list(A,B,C,D) ABCD <- cbind(obj.list)

Actualmente, la única solución que puedo pensar es usar paste() , cat() , write.table() y source() para construir los argumentos a cbind() , escribirlos como un script y cbind() . Esto parece un desafío muy desagradable. Además, he do.call() pero parece que no puedo encontrar la manera de lograr lo que quiero con él.


Primero necesita get los objetos que desea y almacenarlos juntos como una lista; si puedes construir sus nombres como cadenas, usas la función get . Aquí creo dos variables, A y B :

> A <- 1:4 > B <- rep(LETTERS[1:2],2)

Luego construyo un vector de caracteres que contiene sus nombres (almacenados como ns ) y get estas variables usando lapply . Luego configuré los nombres de la lista para que sean los mismos que sus nombres originales.

> (ns <- LETTERS[1:2]) [1] "A" "B" > obj.list <- lapply(ns, get) > names(obj.list) <- ns > obj.list $A [1] 1 2 3 4 $B [1] "A" "B" "A" "B"

Entonces puedes usar do.call ; el primer argumento es la función que desea y el segundo es una lista con los argumentos que desea pasarle.

> do.call(cbind, obj.list) A B [1,] "1" "A" [2,] "2" "B" [3,] "3" "A" [4,] "4" "B"

Sin embargo, como aL3xa notas correctamente, esto hace una matriz, no un marco de datos, que puede no ser lo que quieres si las variables son clases diferentes; aquí mi A ha sido forzada a un vector de caracteres en lugar de un vector numérico. Para hacer un marco de datos de una lista, simplemente llama a data.frame ; entonces las clases de las variables se conservan.

> (AB <- data.frame(obj.list)) A B 1 1 A 2 2 B 3 3 A 4 4 B > sapply(AB, class) A B "integer" "factor" > str(AB) ''data.frame'': 4 obs. of 2 variables: $ A: int 1 2 3 4 $ B: Factor w/ 2 levels "A","B": 1 2 1 2


Puede poner todos los vectores en el entorno en lista usando eapply.

obj.list <- eapply(.GlobalEnv,function(x) if(is.vector(x)) x) obj.list <- obj.list[names(obj.list) %in% LETTERS]


Sin embargo, debes tener en cuenta que cbind devolverá un vector atómico (matriz) cuando se aplica únicamente a vectores atómicos (el double en este caso). Como puede ver en las respuestas de @prasad y @ Aaron, el objeto resultante es una matriz. Si especifica otros vectores atómicos (entero, doble, lógico, complejo) junto con el vector de caracteres, se verán obligados a usar el carácter. Y luego tienes un problema: tienes que convertirlos a las clases deseadas. Asi que,

si A, B, C y D son vectores de la misma longitud, se puede crear un archivo ABCD con data.frame

ABCD <- data.frame(A, B, C, D)

Quizás debería preguntar "¿cómo puedo reunir fácilmente varios vectores de igual longitud y ponerlos en un data.frame "? cbind es genial, pero a veces no es lo que estás buscando ...