read - ¿Estrategias para leer en archivos CSV en piezas?
leer csv en r (2)
Tengo un archivo de tamaño moderado (4GB CSV) en una computadora que no tiene suficiente RAM para leerlo (8GB en Windows de 64 bits). En el pasado, simplemente lo había cargado en un nodo de clúster y lo había leído, pero mi nuevo clúster parece limitar arbitrariamente los procesos a 4 GB de RAM (a pesar de que el hardware tiene 16 GB por máquina), por lo que necesito una solución a corto plazo .
¿Hay alguna forma de leer parte de un archivo CSV en R para ajustar las limitaciones de memoria disponibles? De esa manera, podría leer en un tercio del archivo a la vez, repartirlo en las filas y columnas que necesito y luego leer en el siguiente tercio.
Gracias a los comentaristas por señalar que potencialmente puedo leer todo el archivo usando algunos trucos de memoria grandes: Lectura rápida de tablas muy grandes como marcos de datos en R
Puedo pensar en otras soluciones (por ejemplo, abrir en un buen editor de texto, cortar 2/3 de las observaciones, luego cargar en R), pero prefiero evitarlas si es posible.
Por lo tanto, leerlo en pedazos todavía parece ser la mejor manera de hacerlo por el momento.
Podría leerlo en una base de datos usando RSQLite, por ejemplo, y luego usar una declaración SQL para obtener una parte.
Si solo necesita una parte, entonces read.csv.sql
en el paquete sqldf leerá los datos en una base de datos sqlite. Primero, crea la base de datos para usted y los datos no pasan por R, por lo que no se aplicarán las limitaciones de R (que es principalmente RAM en este escenario). En segundo lugar, después de cargar los datos en la base de datos, sqldf lee la salida de una instrucción SQL especificada en R y finalmente destruye la base de datos. Dependiendo de qué tan rápido funcione con sus datos, podría repetir el proceso completo para cada porción si tiene varias.
Solo una línea de código cumple con los tres pasos, por lo que es una tarea sencilla simplemente intentarlo.
DF <- read.csv.sql("myfile.csv", sql=..., ...other args...)
Consulte ?read.csv.sql
y ?sqldf
y también la página de inicio de sqldf .
Sé que este es un hilo muy viejo. Sin embargo, lo he encontrado recientemente porque tuve un problema similar. Después de ver este hilo, noté que no se mencionó una solución visible a este problema. ¡Usa conexiones!
1) Abra una conexión a su archivo
con = file("file.csv", "r")
2) Leer en trozos de código con read.csv
read.csv(con, nrows="CHUNK SIZE",...)
Nota al margen: la definición de clases de clase acelerará enormemente las cosas. Asegúrese de definir las columnas no deseadas como NULL.
3) Haz lo que necesites hacer
4) Repetir.
5) Cierre la conexión.
close(con)
La ventaja de este enfoque es las conexiones. Si omite este paso, es probable que disminuya la velocidad un poco. Al abrir una conexión manualmente, básicamente abre el conjunto de datos y no lo cierra hasta que llama a la función de cierre. Esto significa que a medida que recorre el conjunto de datos, nunca perderá su lugar. Imagina que tienes un conjunto de datos con 1e7 filas. También imagina que quieres cargar una porción de 1e5 filas a la vez. Desde que abrimos la conexión, obtenemos las primeras filas 1e5 ejecutando read.csv(con, nrow=1e5,...)
, luego, para obtener la segunda parte, ejecutamos read.csv(con, nrow=1e5,...)
así, y así sucesivamente ....
Si no read.csv("file.csv", nrow=1e5,...)
las conexiones, obtendríamos el primer fragmento de la misma forma, read.csv("file.csv", nrow=1e5,...)
, sin embargo, para el siguiente fragmento necesitaremos read.csv("file.csv", skip = 1e5, nrow=2e5,...)
. Claramente esto es ineficiente. Tenemos que encontrar la fila 1e5 + 1 de nuevo, a pesar de que acabamos de leer en la fila 1e5.
Finalmente, data.table::fread
es genial. Pero no se pueden pasar las conexiones. Así que este enfoque no funciona.
Espero que esto ayude a alguien.
ACTUALIZAR
La gente sigue votando este post, así que pensé en agregar un breve pensamiento más. El nuevo readr::read_csv
, como read.csv
, puede pasar las conexiones. Sin embargo, se advertised que es aproximadamente 10 veces más rápido.