Cómo optimizar pandas cuando se trabaja con grandes conjuntos de datos (ensayo)

Cuando la memoria de los vagones y / o un pequeño conjunto de datos se puede lanzar de forma segura a los pandas sin ninguna optimización. Sin embargo, si los datos son grandes, surge la pregunta de cómo procesarlos o al menos contarlos.

Se propone observar la optimización en miniatura para no extraer conjuntos de datos gigantes de la red.

Como conjunto de datos, utilizaremos las estadísticas de hab con los comentarios de los usuarios para 2019, que están disponibles públicamente gracias a un usuario trabajador:
conjunto de datos

Como base de información, se utilizará el artículo traducido previamente de Habr, en el que se mezclan muchas cosas interesantes.

En lugar de unirse


El conjunto de datos habrastatistics se considera pequeño, aunque ocupa 288 MB y consta de 448.533 líneas.
Por supuesto, puede encontrar más datos, pero para no colgar el automóvil, permítanos analizarlo.

Para la conveniencia de las operaciones, agregaremos (solo escriba la primera línea al archivo) los nombres de columna:

a,b,c,d 

Ahora, si carga directamente el conjunto de datos en pandas y verifica cuánta memoria usa

 import os import time import pandas as pd import numpy as np gl = pd.read_csv('habr_2019_comments.csv',encoding='UTF') def mem_usage(pandas_obj): if isinstance(pandas_obj,pd.DataFrame): usage_b = pandas_obj.memory_usage(deep=True).sum() else: #     ,     DataFrame,   Series usage_b = pandas_obj.memory_usage(deep=True) usage_mb = usage_b / 1024 ** 2 #     return "{:03.2f} MB".format(usage_mb) print (gl.info(memory_usage='deep')) 

ver que "come" 436.1 MB:

 RangeIndex: 448533 entries, 0 to 448532 Data columns (total 4 columns): a 448533 non-null object b 448533 non-null object c 448533 non-null object d 448528 non-null object dtypes: object(4) memory usage: 436.1 MB 

También muestra que estamos tratando con columnas que contienen datos de tipo objeto.
Por lo tanto, según el artículo , para las columnas, es necesario centrarse en la optimización calculada para el objeto. Para todas las columnas excepto una.

La columna b contiene fechas y, para la conveniencia de más cálculos y claridad, es mejor enviarlos al índice del conjunto de datos. Para hacer esto, cambie el código utilizado al leer el conjunto de datos:

 gl = pd.read_csv('habr_2019_comments.csv', parse_dates=['b'], encoding='UTF') 

Ahora las fechas se leen como el índice del conjunto de datos y el consumo de memoria se reduce ligeramente:

 memory usage: 407.0 MB 

Ahora optimizamos los datos en el conjunto de datos fuera de las columnas y el índice


La optimización se llama: "Optimización del almacenamiento de datos de tipos de objetos utilizando variables categóricas".

Si se traduce al ruso, entonces debemos combinar los datos en las columnas por categoría, donde sea efectivo.

Para determinar la efectividad, debe conocer el número de valores únicos en las columnas y si es inferior al 50% del número total de valores en la columna, entonces combinar los valores en la categoría será efectivo.

Veamos el conjunto de datos:

 gl_obj=gl.select_dtypes(include=['object']).copy() gl_obj.describe() 
:
  acd count 448533 448533 448528 unique 25100 185 447059 top VolCh 0 ! freq 3377 260438 184 

* columna con fechas en el índice y no mostrada

Como puede ver, desde la fila única, en las columnas ayc, fusionándose eficientemente en categorías. Para la columna a, estos son 25100 usuarios (obviamente menos de 448533), para los valores de c - 185 de la escala con "+" y "-" (también significativamente menos de 448533).

Optimizamos las columnas:

 for col in gl_obj.columns: num_unique_values = len(gl_obj[col].unique()) num_total_values = len(gl_obj[col]) if num_unique_values / num_total_values < 0.5: converted_obj.loc[:,col] = gl_obj[col].astype('category') else: converted_obj.loc[:,col] = gl_obj[col] 

Para comprender cuánta memoria se usa por conveniencia, presentamos una función:

 def mem_usage(pandas_obj): if isinstance(pandas_obj,pd.DataFrame): usage_b = pandas_obj.memory_usage(deep=True).sum() else: #     ,     DataFrame,   Series usage_b = pandas_obj.memory_usage(deep=True) usage_mb = usage_b / 1024 ** 2 #     return "{:03.2f} MB".format(usage_mb) 

Y verifique si la optimización fue efectiva:

 >>> print('  : '+mem_usage(gl_obj))   : 407.14 MB >>> print('  : '+mem_usage(converted_obj))   : 356.40 MB >>> 

Como puede ver, se recibió una ganancia de otros 50 MB.

Ahora, habiendo entendido que la optimización se ha beneficiado (sucede y viceversa), estableceremos los parámetros del conjunto de datos al leer para tener en cuenta de inmediato los datos que estamos tratando:

 gl = pd.read_csv('habr_2019_comments.csv', parse_dates=['b'],index_col='b',dtype ={'c':'category','a':'category','d':'object'}, encoding='UTF') 

¡Le deseamos un trabajo rápido con conjuntos de datos!

El código para descargar está aquí .

Source: https://habr.com/ru/post/467785/


All Articles