R: cómo enlazar dos enormes marcos de datos sin quedarse sin memoria

Tengo dos marcos de datos df1 y df2 que tienen alrededor de 10 millones de filas y 4 columnas. Los leí en R usando RODBC / sqlQuery sin problemas, pero cuando trato de rbind , obtengo los mensajes de error más temidos: cannot allocate memory . Tiene que haber formas más eficientes de hacer un rbind más eficiente: ¿alguien tiene sus trucos favoritos sobre esto que quiere compartir? Por ejemplo, encontré este ejemplo en el documento para sqldf :

 # rbind a7r <- rbind(a5r, a6r) a7s <- sqldf("select * from a5s union all select * from a6s") 

¿Es esa la mejor / manera recomendada de hacerlo?

ACTUALIZACIÓN Lo hice funcionar usando el dbname = tempfile() crucial dbname = tempfile() en la llamada sqldf anterior, como sugiere JD Long en su respuesta a esta pregunta

En lugar de leerlos en R al principio y luego combinarlos, puede hacer que SQLite los lea y los combine antes de enviarlos a R. De esta forma, los archivos nunca se cargan individualmente en R.

 # create two sample files DF1 <- data.frame(A = 1:2, B = 2:3) write.table(DF1, "data1.dat", sep = ",", quote = FALSE) rm(DF1) DF2 <- data.frame(A = 10:11, B = 12:13) write.table(DF2, "data2.dat", sep = ",", quote = FALSE) rm(DF2) # now we do the real work library(sqldf) data1 <- file("data1.dat") data2 <- file("data2.dat") sqldf(c("select * from data1", "insert into data1 select * from data2", "select * from data1"), dbname = tempfile()) 

Esto da:

 > sqldf(c("select * from data1", "insert into data1 select * from data2", "select * from data1"), dbname = tempfile()) AB 1 1 2 2 2 3 3 10 12 4 11 13 

Esta versión más corta también funciona si el orden de las filas no es importante:

 sqldf("select * from data1 union select * from data2", dbname = tempfile()) 

Consulte la página de inicio sqldf http://sqldf.googlecode.com y ?sqldf para obtener más información. Preste especial atención a los argumentos de formato de archivo, ya que están cerca pero no son idénticos a read.table . Aquí hemos utilizado los valores predeterminados, por lo que fue un problema menor.

Observe el paquete data.table R para operaciones eficientes en objetos con más de varios millones de registros.

La versión 1.8.2 de ese paquete ofrece la función rbindlist través de la cual puede lograr lo que quiere de manera muy eficiente. Por lo tanto, en lugar de rbind(a5r, a6r) puedes:

 library(data.table) rbindlist(list(a5r, a6r)) 

Intente crear un data.frame del tamaño deseado, por lo tanto, importe sus datos usando subíndices.

 dtf <- as.data.frame(matrix(NA, 10, 10)) dtf1 <- as.data.frame(matrix(1:50, 5, 10, byrow=TRUE)) dtf2 <- as.data.frame(matrix(51:100, 5, 10, byrow=TRUE)) dtf[1:5, ] <- dtf1 dtf[6:10, ] <- dtf2 

Supongo que rbind objeto crece sin preasignar sus dimensiones ... No estoy seguro, esto es solo una suposición. Peinaré "The R Inferno" o "Data Manipulation with R" esta noche. Tal vez merge hará el truco ...

EDITAR

Y debes tener en cuenta que (tal vez) tu sistema y / o R no pueden hacer frente a algo tan grande. Pruebe RevolutionR, tal vez logre ahorrar tiempo / recursos.

Para completar este hilo sobre el tema de la unión: en archivos grandes, intente usar comandos de shell en los archivos para combinarlos. En Windows, el comando es “COPIA” con el indicador “/ B”. Ejemplo:

 system(command = paste0( c("cmd.exe /c COPY /Y" , '"file_1.csv" /B' , '+ "file_2.csv" /B' , '"resulting_file.csv" /B' ), collapse = " " ) )#system 

Requiere que los archivos no tengan encabezado, y el mismo delimitador, etc. La velocidad y versatilidad de los comandos de shell a veces es una gran ventaja, así que no se olvide de los comandos CLI al mapear flujos de datos.