R: cómo rbind dos grandes marcos de datos sin el funcionamiento de la memoria
-
16-10-2019 - |
Pregunta
Tengo df1
y df2
que tienen cada uno alrededor de 10 millones de filas y 4 columnas dos marcos de datos. Los leí en R utilizando RODBC / SQLQuery sin ningún problema, pero cuando trato de rbind
ellos, lo entiendo más temida de mensajes de error R: cannot allocate memory
. No tienen que ser formas más eficientes de hacer un rbind
más eficiente - cualquier persona tiene sus trucos preferidos en este quieren compartir? Por ejemplo me encontré con este ejemplo en el doc para sqldf
:
# rbind
a7r <- rbind(a5r, a6r)
a7s <- sqldf("select * from a5s union all select * from a6s")
Es que la mejor manera / recomienda para hacerlo?
Actualizar
Yo tengo que trabajar con el argumento dbname = tempfile()
crucial en la llamada sqldf
anterior, como JD largo sugiere en su respuesta a esta pregunta
Solución
En lugar de leerlos en R al principio y luego la combinación de ellos podría tener SQLite los leyó y combinarlos antes de enviarlos a R. De esta manera 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())
A B
1 1 2
2 2 3
3 10 12
4 11 13
Esta versión más corta también funciona si orden de las filas no es importante:
sqldf("select * from data1 union select * from data2", dbname = tempfile())
Vea la página principal sqldf http://sqldf.googlecode.com y ?sqldf
para obtener más información. Prestar especial atención a los argumentos de formato de archivo, ya que están cerca, pero no idéntica a read.table
. Aquí hemos utilizado los valores por defecto por lo que era un problema menor.
Otros consejos
Aviso data.table
el paquete R para operaciones eficientes en objetos con varios millones de registros.
Versión 1.8.2 de que las ofertas de paquetes de la función rbindlist
a través del cual se puede lograr lo que desea de manera muy eficiente. Así, en lugar de rbind(a5r, a6r)
puede:
library(data.table)
rbindlist(list(a5r, a6r))
Trate de crear un data.frame
del tamaño deseado, por lo tanto, la importación de los datos con 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 crece rbind
objeto sin pre-asignación de sus dimensiones ... No estoy completamente seguro, esto es sólo una conjetura. Voy a peinar hacia abajo "El R Inferno" o "manipulación de datos con R" esta noche. Tal vez merge
hará el truco ...
Editar
Y usted debe desnudo en cuenta que (tal vez) el sistema y / o R no pueden hacer frente a algo tan grande. Trate RevolutionR, tal vez consigas a un poco de tiempo / recursos.
Para completar en este hilo sobre el tema de la unión: ing archivos de gran tamaño, pruebe a utilizar los comandos de shell en los archivos de combinarlos. En Windows que se comando "COPY" con la bandera "A / 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 tienen cabecera, y el mismo delimitador, etc, etc. La velocidad y la versatilidad de comandos shell es a veces un gran beneficio, por lo que no se olvide de la CLI-comandos cuando mapeo de flujos de datos.