Actualmente estoy tratando de abrir un archivo con pandas y python para fines de aprendizaje automático, sería ideal para mí tenerlos a todos en un DataFrame. Ahora el archivo es de 18 GB y mi RAM es de 32 GB, pero sigo recibiendo errores de memoria.
Desde su experiencia, ¿es posible? Si no, ¿sabes de una mejor manera de evitar esto? (¿tabla de colmena? aumentar el tamaño de mi RAM a 64? crear una base de datos y acceder a ella desde python)
pandas
es que debe tener de 5 a 10 veces más RAM. Recomiendo hacerinplace
operaciones, llamar explícitamentegarbage.collector
para desasignar objetos.Respuestas:
Si es un archivo csv y no necesita acceder a todos los datos a la vez al entrenar su algoritmo, puede leerlo en fragmentos. El
pandas.read_csv
método le permite leer un archivo en fragmentos como este:Aquí está la documentación del método.
fuente
Hay dos posibilidades: o necesita tener todos sus datos en la memoria para el procesamiento (por ejemplo, su algoritmo de aprendizaje automático querría consumirlos todos a la vez), o puede prescindir de ellos (por ejemplo, su algoritmo solo necesita muestras de filas o columnas a la vez).
En el primer caso, deberá resolver un problema de memoria . Aumente el tamaño de su memoria, alquile una máquina en la nube de alta memoria, use operaciones in situ, brinde información sobre el tipo de datos que está leyendo, asegúrese de eliminar todas las variables no utilizadas y recolectar basura, etc.
Es muy probable que 32 GB de RAM no sean suficientes para que Pandas maneje sus datos. Tenga en cuenta que el número entero "1" es solo un byte cuando se almacena como texto, pero 8 bytes cuando se representa como
int64
(que es el valor predeterminado cuando Pandas lo lee desde el texto). Puede hacer el mismo ejemplo con un número de coma flotante "1.0" que se expande de una cadena de 3 bytes a 8 bytesfloat64
de forma predeterminada. Puede ganar algo de espacio al hacer que Pandas sepa con precisión qué tipos usar para cada columna y forzar las representaciones más pequeñas posibles, pero ni siquiera comenzamos a hablar de la estructura de datos de Python aquí, lo que puede agregar un puntero adicional o dos aquí o allá fácilmente , y los punteros son de 8 bytes cada uno en una máquina de 64 bits.Para resumir: no, 32 GB de RAM probablemente no sea suficiente para que Pandas maneje un archivo de 20 GB.
En el segundo caso (que es más realista y probablemente se aplica a usted), debe resolver un problema de gestión de datos . De hecho, tener que cargar todos los datos cuando realmente solo necesita partes de ellos para el procesamiento, puede ser un signo de mala gestión de datos. Hay varias opciones aquí:
Use una base de datos SQL. Si puede, es casi siempre la primera opción y una solución decentemente cómoda. 20 GB suena como el tamaño que la mayoría de las bases de datos SQL manejarían bien sin la necesidad de distribuirse incluso en una computadora portátil (de gama alta). Podrá indexar columnas, hacer agregaciones básicas a través de SQL y obtener las submuestras necesarias en Pandas para un procesamiento más complejo utilizando un simple
pd.read_sql
. Mover los datos a una base de datos también le brindará la oportunidad de pensar en los tipos y tamaños de datos reales de sus columnas.Si sus datos son en su mayoría numéricos (es decir, matrices o tensores), puede considerar guardarlos en un formato HDF5 (consulte PyTables ), lo que le permite leer convenientemente solo las porciones necesarias de matrices enormes del disco. Básico numpy.save y numpy.load lograr el mismo efecto mediante mapeo de memoria en las matrices en el disco también. Para los SIG y los datos ráster relacionados, existen bases de datos dedicadas , que podrían no conectarse a los pandas tan directamente como SQL, pero también deberían permitirle realizar cortes y consultas de manera razonablemente conveniente.
Pandas no admite ese mapeo de memoria "parcial" de HDF5 o matrices numpy, que yo sepa. Si aún desea un tipo de solución de "pandas puros", puede intentar "fragmentar": almacenando las columnas de su tabla enorme por separado (por ejemplo, en archivos separados o en "tablas" separadas de un solo HDF5 archivo) y solo carga los necesarios a pedido, o almacena los trozos de filas por separado. Sin embargo, necesitaría implementar la lógica para cargar los fragmentos necesarios, reinventando las bicicletas ya implementadas en la mayoría de las bases de datos SQL, por lo que quizás la opción 1 aún sería más fácil aquí. Sin embargo, si sus datos vienen en un CSV, puede procesarlos en fragmentos especificando el
chunksize
parámetro apd.read_csv
.fuente
¡Acabo de tener este problema hace unos días! No estoy seguro de si esto ayuda en su caso específico, ya que no proporciona tantos detalles, pero mi situación era trabajar sin conexión en un conjunto de datos 'grande'. Los datos se obtuvieron como archivos CSV comprimidos de 20 GB de medidores de energía, datos de series de tiempo a intervalos de varios segundos.
Archivo IO:
Cree un iterador de fragmentos directamente sobre el archivo gzip (¡no lo descomprima!)
Iterar sobre los trozos
Dentro del bucle de fragmentos, estoy filtrando y volviendo a muestrear a tiempo. Al hacer esto, reduje el tamaño de 20 GB a unos pocos cientos de MB HDF5 para una mayor exploración de datos fuera de línea.
fuente
En mi experiencia, la inicialización
read_csv()
con parámetroslow_memory=False
tiende a ayudar cuando se lee en archivos grandes. No creo que haya mencionado el tipo de archivo en el que está leyendo, por lo que no estoy seguro de qué tan aplicable es a su situación.fuente
Si su archivo es un CSV, simplemente puede hacerlo en Chunk by Chunk. Simplemente puedes hacer:
fuente