2011-11-01 8 views
5

Estoy tratando de combinar una cantidad de dataframes usando rbind. Si llamo o directamente rbind no hay ningún problema:perdiendo dataframe al usar do.call

> test <- rbind(x) 
> is.data.frame(x) 
[1] TRUE 

Sin embargo, si uso do.call me encuentro con un problema en el que se contraen mis columnas de caracteres y la trama de datos se convierte en una matriz.

>test <- do.call("rbind", x) 
> is.data.frame(test) 
[1] FALSE 

Según el? Documentación rbind Traté add stringsAsFactors = FALSE pero ningún cambio en el comportamiento. Mis tablas de datos tienen el siguiente aspecto:

ID sequence descriptor 
1 aaacccttt g12 
2 actttgtgt e34 
3 tttgggctc b12 
4 ccgcgcgcg c12 
… …  ... 

y la salida rbind se parece a esto, pero la salida do.call("rbind", x) aparece como sigue, donde la columna de la secuencia ya no es un personaje:

ID 363 426 91 
Sequence 98 353 100 
descriptor g12 b12 c12 

me gustaría para usar do.call porque estoy recorriendo un conjunto de dataframes para consolidarlos usando un script a continuación. Otra respuesta útil podría ofrecer una solución alternativa sobre cómo combinar múltiples marcos de datos mientras los llama en un bucle.

stringsAsFactors = FALSE 
dfs <- as.list(ls(pattern="Data_")) 
for (i in 1:length(dfs)) { 
    x <- get(as.character(dfs[i])) 
    AllData <- do.call("rbind", x) 
    } 

dfs es la lista de tramas de datos en mi ambiente de trabajo y tengo la trama de datos real utilizando get

gracias.

Respuesta

4

Hay dos problemas diferentes que le causan dificultades.

  • stringsAsFactors

Tienes razón que se busca en stringsAsFactors, pero simplemente no lo han llamado en todo el lugar correcto.

Tiene dos opciones. Usted puede ponerlo en su options, así:

options(stringsAsFactors=FALSE) 

O en el código utilizado para crear sus data.table s:

a <- read.table(textConnection("ID sequence descriptor 
1 aaacccttt g12 
2 actttgtgt e34 
3 tttgggctc b12 
4 ccgcgcgcg c12"), 
header=T, stringsAsFactors=FALSE) 
  • args= argumento a do.call()

usted También estoy en el camino correcto al querer usar do.call() para esto. Pero, como @Sacha señala, dfs debe ser una lista de data.frame s, no una sola data.frame (que a su vez es una lista de vectores).

# Create list of two data.frames 
b <- a 
dfs <- list(a, b) 

# Or, if you start with a list of their names 
dfs <- list("a", "b") 
dfs <- lapply(dfs, get) 

# Check that this works 
do.call("rbind", dfs) 
# ID sequence descriptor 
# 1 1 aaacccttt  g12 
# 2 2 actttgtgt  e34 
# 3 3 tttgggctc  b12 
# 4 4 ccgcgcgcg  c12 
# 5 1 aaacccttt  g12 
# 6 2 actttgtgt  e34 
# 7 3 tttgggctc  b12 
# 8 4 ccgcgcgcg  c12 

Esto también se debe trabajar para usted, incluso si sólo tiene un único data.frame, siempre que se envuelve en un (longitud-1) list, así: dfs <- list(a)

+0

que es una respuesta increíble. – zach

2

El uso de código de ejemplo Josh' .Estoy bastante seguro de que lo que ocurre es lo siguiente:

Data: 
    x <- read.table(textConnection("ID sequence descriptor 
    1 aaacccttt g12 
    2 actttgtgt e34 
    3 tttgggctc b12 
    4 ccgcgcgcg c12"), 
    header=T, stringsAsFactors=FALSE) 

En primer lugar esto:

rbind(x) 

no hace nada ya que sólo hay un argumento. Es decir. no hay nada que anexar al marco de datos por lo que solo devuelve el mismo marco de datos. Entonces:

do.call("rbind", x) 

Lo que sucede aquí es que rbind() se llama con todos los argumentos de la lista x. Un marco de datos es una lista con columnas como elementos. Por lo tanto, esto sería lo mismo que:

rbind(x$ID,x$sequence,x$descriptor) 

por lo que pone tres vectores juntos por fila. Por lo tanto, esto se convierte en la transposición de lo que tenía y dado que data.frames solo almacena diferentes tipos de vectores en forma de columna, esto debe convertirse en una matriz de caracteres.

Creo que si x es una lista de marcos de datos funciona bien. Simplemente no debería ser un marco de datos en sí mismo.

+0

gracias Sacha, creo que has descrito perfectamente lo que está pasando – zach

1

Creo que lo que buscas se puede hacer sin un bucle usando Reduce. Es una función de orden superior, que sucesivamente aplica una función a dos elementos de una lista.

dfs <- as.list(ls(pattern="Data_")) 
Reduce('rbind', dfs) 
+0

gracias Ramnath, sin embargo, cuando intento este enfoque, no devuelvo un conjunto de datos sino una matriz de caracteres. No sabía acerca de Reducir, así que definitivamente lo investigaré. – zach

Cuestiones relacionadas