He intentado descifrar una respuesta a esta pregunta durante muchos meses mientras aprendía pandas. Utilizo SAS para mi trabajo diario y es excelente por su soporte fuera del núcleo. Sin embargo, SAS es horrible como una pieza de software por muchas otras razones.
Un día espero reemplazar mi uso de SAS con python y pandas, pero actualmente no tengo un flujo de trabajo fuera de núcleo para grandes conjuntos de datos. No estoy hablando de "big data" que requiere una red distribuida, sino archivos demasiado grandes para caber en la memoria pero lo suficientemente pequeños como para caber en un disco duro.
Mi primer pensamiento es usar HDFStore
para mantener grandes conjuntos de datos en el disco y extraer solo las piezas que necesito en los marcos de datos para su análisis. Otros han mencionado a MongoDB como una alternativa más fácil de usar. Mi pregunta es esta:
¿Cuáles son algunos flujos de trabajo de mejores prácticas para lograr lo siguiente?
- Carga de archivos planos en una estructura de base de datos permanente en disco
- Consultar esa base de datos para recuperar datos para alimentar una estructura de datos de pandas
- Actualización de la base de datos después de manipular piezas en pandas
Los ejemplos del mundo real serían muy apreciados, especialmente de cualquiera que use pandas en "datos grandes".
Editar: un ejemplo de cómo me gustaría que esto funcione:
- Importe iterativamente un archivo plano grande y guárdelo en una estructura de base de datos permanente en el disco. Estos archivos suelen ser demasiado grandes para caber en la memoria.
- Para usar Pandas, me gustaría leer subconjuntos de estos datos (generalmente solo unas pocas columnas a la vez) que pueden caber en la memoria.
- Crearía nuevas columnas realizando varias operaciones en las columnas seleccionadas.
- Entonces tendría que agregar estas nuevas columnas a la estructura de la base de datos.
Estoy tratando de encontrar una forma práctica recomendada de realizar estos pasos. Al leer enlaces sobre pandas y pytables parece que agregar una nueva columna podría ser un problema.
Editar - Respondiendo a las preguntas de Jeff específicamente:
- Estoy construyendo modelos de riesgo de crédito al consumo. Los tipos de datos incluyen teléfono, número de seguro social y características de la dirección; valores de propiedad; información despectiva como antecedentes penales, quiebras, etc. Los conjuntos de datos que uso todos los días tienen casi 1,000 a 2,000 campos en promedio de tipos de datos mixtos: variables continuas, nominales y ordinales de datos numéricos y de caracteres. Raramente agrego filas, pero realizo muchas operaciones que crean nuevas columnas.
- Las operaciones típicas implican combinar varias columnas usando lógica condicional en una nueva columna compuesta. Por ejemplo,
if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B'
. El resultado de estas operaciones es una nueva columna para cada registro en mi conjunto de datos. - Finalmente, me gustaría agregar estas nuevas columnas a la estructura de datos en disco. Repetiría el paso 2, explorando los datos con tablas de referencias cruzadas y estadísticas descriptivas tratando de encontrar relaciones interesantes e intuitivas para modelar.
- Un archivo de proyecto típico suele ser de aproximadamente 1 GB. Los archivos están organizados de tal manera que una fila consiste en un registro de datos del consumidor. Cada fila tiene el mismo número de columnas para cada registro. Este siempre será el caso.
- Es bastante raro que yo subconjunto por filas al crear una nueva columna. Sin embargo, es bastante común para mí subconjuntar en filas al crear informes o generar estadísticas descriptivas. Por ejemplo, podría querer crear una frecuencia simple para una línea de negocios específica, por ejemplo, tarjetas de crédito minoristas. Para hacer esto, seleccionaría solo aquellos registros donde la línea de negocio = minorista, además de las columnas sobre las que deseo informar. Sin embargo, al crear nuevas columnas, extraería todas las filas de datos y solo las columnas que necesito para las operaciones.
- El proceso de modelado requiere que analice cada columna, busque relaciones interesantes con alguna variable de resultado y cree nuevas columnas compuestas que describan esas relaciones. Las columnas que exploro generalmente se hacen en pequeños conjuntos. Por ejemplo, me enfocaré en un conjunto de, digamos, 20 columnas que solo tratan los valores de las propiedades y observaré cómo se relacionan con el incumplimiento de un préstamo. Una vez que se exploran y se crean nuevas columnas, luego paso a otro grupo de columnas, digo educación universitaria y repito el proceso. Lo que estoy haciendo es crear variables candidatas que expliquen la relación entre mis datos y algunos resultados. Al final de este proceso, aplico algunas técnicas de aprendizaje que crean una ecuación a partir de esas columnas compuestas.
Es raro que alguna vez agregue filas al conjunto de datos. Casi siempre crearé nuevas columnas (variables o características en estadísticas / lenguaje de aprendizaje automático).
Respuestas:
Rutinariamente uso decenas de gigabytes de datos de esta manera, por ejemplo, tengo tablas en el disco que leo a través de consultas, creo datos y vuelvo a agregar.
Vale la pena leer los documentos y al final de este hilo para obtener varias sugerencias sobre cómo almacenar sus datos.
Detalles que afectarán la forma en que almacena sus datos, como:
Proporcione tantos detalles como pueda; y puedo ayudarte a desarrollar una estructura.
(Dar un ejemplo de juguete podría permitirnos ofrecer recomendaciones más específicas).
Solución
Asegúrese de tener al menos pandas
0.10.1
instalados.Lea archivos iterativos trozo por trozo y múltiples consultas de tabla .
Dado que pytables está optimizado para operar en filas (que es lo que consulta), crearemos una tabla para cada grupo de campos. De esta manera, es fácil seleccionar un pequeño grupo de campos (que funcionará con una tabla grande, pero es más eficiente hacerlo de esta manera ... Creo que podría solucionar esta limitación en el futuro ... esto es más intuitivo de todos modos):
(Lo siguiente es pseudocódigo).
Lectura de los archivos y creación del almacenamiento (esencialmente haciendo lo que
append_to_multiple
hace):Ahora tiene todas las tablas en el archivo (en realidad podría almacenarlas en archivos separados si lo desea, probablemente tendría que agregar el nombre del archivo al mapa_grupo, pero probablemente esto no sea necesario).
Así es como obtienes columnas y creas nuevas:
Cuando esté listo para post_procesamiento:
Acerca de data_columns, en realidad no necesita definir CUALQUIER data_columns; te permiten subseleccionar filas según la columna. Por ejemplo, algo como:
Pueden ser más interesantes para usted en la etapa de generación del informe final (esencialmente una columna de datos está segregada de otras columnas, lo que podría impactar un poco la eficiencia si define mucho).
También es posible que desee:
¡Avísame cuando tengas preguntas!
fuente
Creo que a las respuestas anteriores les falta un enfoque simple que he encontrado muy útil.
Cuando tengo un archivo que es demasiado grande para cargarlo en la memoria, lo divido en varios archivos más pequeños (ya sea por filas o por columnas)
Ejemplo: en el caso de 30 días de datos comerciales de ~ 30 GB de tamaño, lo divido en un archivo por día de ~ 1 GB de tamaño. Posteriormente, proceso cada archivo por separado y agrego los resultados al final
Una de las mayores ventajas es que permite el procesamiento paralelo de los archivos (ya sea múltiples hilos o procesos)
La otra ventaja es que la manipulación de archivos (como agregar / eliminar fechas en el ejemplo) se puede lograr mediante comandos de shell regulares, lo que no es posible en formatos de archivo más avanzados / complicados
Este enfoque no cubre todos los escenarios, pero es muy útil en muchos de ellos.
fuente
Ahora hay, dos años después de la pregunta, un pandas 'fuera de núcleo' equivalente: dask . ¡Es excelente! Aunque no admite todas las funciones de pandas, puedes llegar muy lejos con él.
fuente
dask
.Si sus conjuntos de datos tienen entre 1 y 20 GB, debería obtener una estación de trabajo con 48 GB de RAM. Entonces Pandas puede contener todo el conjunto de datos en la RAM. Sé que no es la respuesta que está buscando aquí, pero hacer computación científica en una computadora portátil con 4 GB de RAM no es razonable.
fuente
Sé que este es un hilo antiguo, pero creo que vale la pena echarle un vistazo a la biblioteca Blaze . Está construido para este tipo de situaciones.
De los documentos:
Blaze extiende la usabilidad de NumPy y Pandas a la computación distribuida y fuera del núcleo. Blaze proporciona una interfaz similar a la de NumPy ND-Array o Pandas DataFrame, pero asigna estas interfaces familiares en una variedad de otros motores computacionales como Postgres o Spark.
Editar: Por cierto, es compatible con ContinuumIO y Travis Oliphant, autor de NumPy.
fuente
Este es el caso de pymongo. También he realizado un prototipo utilizando sql server, sqlite, HDF, ORM (SQLAlchemy) en python. En primer lugar, pymongo es una base de datos basada en documentos, por lo que cada persona sería un documento (
dict
de atributos). Muchas personas forman una colección y usted puede tener muchas colecciones (personas, bolsa de valores, ingresos).pd.dateframe -> pymongo Nota: uso el
chunksize
inread_csv
para mantenerlo en 5 a 10k registros (pymongo cae el socket si es más grande)consultas: gt = mayor que ...
.find()
devuelve un iterador, por lo que comúnmente usoichunked
para cortar en iteradores más pequeños.¿Qué tal una unión ya que normalmente obtengo 10 fuentes de datos para pegar?
entonces (en mi caso, a veces tengo que agregar
aJoinDF
antes de que sea "fusionable").Y luego puede escribir la nueva información en su colección principal a través del método de actualización a continuación. (colección lógica vs fuentes de datos físicas).
En búsquedas más pequeñas, solo desnormalizar. Por ejemplo, tiene código en el documento y simplemente agrega el texto del código de campo y realiza una
dict
búsqueda a medida que crea documentos.Ahora que tiene un buen conjunto de datos basado en una persona, puede liberar su lógica en cada caso y hacer más atributos. Finalmente, puede leer en pandas sus 3 indicadores clave de memoria máxima y hacer pivotes / agg / exploración de datos. Esto me funciona para 3 millones de registros con números / texto grande / categorías / códigos / flotantes / ...
También puede usar los dos métodos integrados en MongoDB (MapReduce y el marco agregado). Consulte aquí para obtener más información sobre el marco agregado , ya que parece ser más fácil que MapReduce y parece útil para un trabajo agregado rápido. Observe que no necesitaba definir mis campos o relaciones, y puedo agregar elementos a un documento. En el estado actual del conjunto de herramientas de numpy, pandas y python que cambia rápidamente, MongoDB me ayuda a ponerme a trabajar :)
fuente
In [96]: test.insert((a[1].to_dict() for a in df.iterrows())) --------------- InvalidDocument: Cannot encode object: 0
. ¿Alguna idea de lo que podría estar mal? Mi marco de datos consta de todos los tipos de int64 y es muy simple.Lo vi un poco tarde, pero trabajo con un problema similar (modelos de prepago de hipoteca). Mi solución ha sido omitir la capa HDFStore de pandas y usar pytables rectas. Guardo cada columna como una matriz HDF5 individual en mi archivo final.
Mi flujo de trabajo básico es obtener primero un archivo CSV de la base de datos. Lo comprimo, así que no es tan grande. Luego lo convierto en un archivo HDF5 orientado a filas, iterando sobre él en python, convirtiendo cada fila a un tipo de datos real y escribiéndolo en un archivo HDF5. Eso lleva algunas decenas de minutos, pero no usa memoria, ya que solo funciona fila por fila. Luego "transpongo" el archivo HDF5 orientado a filas en un archivo HDF5 orientado a columnas.
La transposición de la tabla se ve así:
Leerlo de nuevo y luego se ve así:
Ahora, generalmente ejecuto esto en una máquina con una tonelada de memoria, por lo que es posible que no sea lo suficientemente cuidadoso con mi uso de memoria. Por ejemplo, de manera predeterminada, la operación de carga lee todo el conjunto de datos.
Esto generalmente funciona para mí, pero es un poco torpe, y no puedo usar la elegante magia de las tablas.
Editar: La ventaja real de este enfoque, sobre el valor predeterminado de pytables de la matriz de registros, es que luego puedo cargar los datos en R usando h5r, que no puede manejar tablas. O, al menos, no he podido hacer que cargue tablas heterogéneas.
fuente
Un truco que encontré útil para casos de uso de datos grandes es reducir el volumen de datos al reducir la precisión de flotación a 32 bits. No es aplicable en todos los casos, pero en muchas aplicaciones la precisión de 64 bits es exagerada y los ahorros de memoria 2x valen la pena. Para hacer un punto obvio aún más obvio:
fuente
Como han señalado otros, después de algunos años ha surgido un equivalente de pandas 'fuera de núcleo': dask . Aunque dask no es un reemplazo directo de los pandas y toda su funcionalidad, se destaca por varias razones:
Dask es una biblioteca de computación paralela flexible para computación analítica que está optimizada para la programación dinámica de tareas para cargas de trabajo computacionales interactivas de colecciones de "Big Data", como matrices paralelas, marcos de datos y listas que extienden interfaces comunes como iteradores NumPy, Pandas o Python a grandes. que la memoria o entornos distribuidos y escalas de computadoras portátiles a clústeres.
y para agregar una muestra de código simple:
reemplaza algunos códigos de pandas como este:
y, especialmente notable, proporciona a través de la
concurrent.futures
interfaz una infraestructura general para el envío de tareas personalizadas:fuente
Vale la pena mencionar aquí Ray también,
es un marco de cómputo distribuido, que tiene su propia implementación para pandas de manera distribuida.
Simplemente reemplace la importación de pandas, y el código debería funcionar como está:
Puede leer más detalles aquí:
https://rise.cs.berkeley.edu/blog/pandas-on-ray/
fuente
Una variante más
Muchas de las operaciones realizadas en pandas también se pueden realizar como una consulta db (sql, mongo)
El uso de un RDBMS o mongodb le permite realizar algunas de las agregaciones en la consulta de base de datos (que está optimizada para datos grandes y utiliza la caché y los índices de manera eficiente)
Más tarde, puede realizar el procesamiento posterior utilizando pandas.
La ventaja de este método es que obtiene las optimizaciones de la base de datos para trabajar con datos de gran tamaño, mientras define la lógica en una sintaxis declarativa de alto nivel, y no tiene que lidiar con los detalles de decidir qué hacer en la memoria y qué hacer. de núcleo.
Y aunque el lenguaje de consulta y los pandas son diferentes, generalmente no es complicado traducir parte de la lógica de uno a otro.
fuente
Considere Ruffus si sigue el camino simple de crear una tubería de datos que se divide en múltiples archivos más pequeños.
fuente
Recientemente me encontré con un problema similar. Descubrí que simplemente leer los datos en fragmentos y agregarlos a medida que los escribo en el mismo csv funciona bien. Mi problema fue agregar una columna de fecha basada en la información en otra tabla, usando el valor de ciertas columnas de la siguiente manera. Esto puede ayudar a aquellos confundidos por dask y hdf5 pero más familiarizados con los pandas como yo.
fuente
Me gustaría señalar el paquete Vaex.
Eche un vistazo a la documentación: https://vaex.readthedocs.io/en/latest/ La API está muy cerca de la API de los pandas.
fuente
¿Por qué pandas? ¿Has probado el estándar Python ?
El uso de la biblioteca estándar de python. Pandas está sujeto a actualizaciones frecuentes, incluso con el reciente lanzamiento de la versión estable.
Usando la biblioteca estándar de Python, su código siempre se ejecutará.
Una forma de hacerlo es tener una idea de la forma en que desea que se almacenen sus datos y qué preguntas desea resolver con respecto a los datos. Luego dibuje un esquema de cómo puede organizar sus datos (tablas de pensamiento) que lo ayudarán a consultar los datos, no necesariamente a la normalización.
Puedes hacer buen uso de:
Ram y HDD se están volviendo más y más baratos con el tiempo y Python 3 estándar está ampliamente disponible y es estable.
fuente
En este momento estoy trabajando "como" usted, solo en una escala más baja, por lo que no tengo un PoC para mi sugerencia.
Sin embargo, parece que tengo éxito en el uso de pickle como sistema de almacenamiento en caché y la subcontratación de la ejecución de varias funciones en archivos, ejecutando estos archivos desde mi comando / archivo principal; Por ejemplo, uso prepare_use.py para convertir tipos de objetos, dividir un conjunto de datos en un conjunto de datos de prueba, validación y predicción.
¿Cómo funciona el almacenamiento en caché con pepinillos? Utilizo cadenas para acceder a los archivos pickle que se crean dinámicamente, dependiendo de qué parámetros y conjuntos de datos se pasaron (con eso trato de capturar y determinar si el programa ya se ejecutó, usando .shape para el conjunto de datos, dict para pasado parámetros). Respetando estas medidas, obtengo una Cadena para tratar de encontrar y leer un archivo .pickle y puedo, si se encuentra, omitir el tiempo de procesamiento para saltar a la ejecución en la que estoy trabajando en este momento.
Al usar bases de datos me encontré con problemas similares, por lo que me gustó usar esta solución, sin embargo, hay muchas restricciones, por ejemplo, almacenar grandes conjuntos de encurtidos debido a la redundancia. La actualización de una tabla desde antes hasta después de una transformación se puede hacer con una indexación adecuada: la validación de la información abre un libro completamente diferente (intenté consolidar los datos de alquiler rastreados y básicamente dejé de usar una base de datos después de 2 horas, ya que me hubiera gustado retroceder después cada proceso de transformación)
Espero que mis 2 centavos te ayuden de alguna manera.
Saludos.
fuente