mtext - R: cómo enlazar dos enormes marcos de datos sin quedarse sin memoria
text in r (4)
Tengo dos marcos de datos df1
y df2
que tienen cada uno alrededor de 10 millones de filas y 4 columnas. Los leí en R usando RODBC / sqlQuery sin problemas, pero cuando intento rbind
, recibo la más temida de los mensajes de error de R: cannot allocate memory
. Tiene que haber maneras 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 forma mejor / recomendada de hacerlo?
ACTUALIZACIÓN Lo hice funcionar usando el 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 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 el orden de las filas no es importante:
sqldf("select * from data1 union select * from data2", dbname = tempfile())
Consulte la página de inicio de 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.
Intente crear un data.frame
de data.frame
del tamaño deseado, por lo tanto, importe sus datos utilizando 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
crecer el objeto sin asignar previamente sus dimensiones ... No estoy seguro de que esto sea solo una suposición. Voy a peinar hacia abajo "The R Inferno" o "Data Manipulation with R" esta noche. Tal vez la merge
hará el truco ...
EDITAR
Y debe tener en cuenta que (tal vez) su sistema y / o R no pueden hacer frente a algo tan grande. Prueba RevolutionR, quizás puedas ahorrar algo de tiempo / recursos.
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))
Para completar este hilo en el tema de la unión: ingiriendo archivos grandes, intente usar comandos de shell en los archivos para combinarlos. En las ventanas es el comando "COPIAR" 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, el mismo delimitador, etc. La velocidad y la versatilidad de los comandos de shell a veces son un gran beneficio, así que no olvide los comandos CLI al asignar flujos de datos.