Como otimizar pandas ao trabalhar com grandes conjuntos de dados (ensaio)

Quando a memória de vagões e / ou um pequeno conjunto de dados pode ser lançada com segurança em pandas sem qualquer otimização. No entanto, se os dados são grandes, surge a questão de como processá-los ou pelo menos contá-los.

Propõe-se analisar a otimização em miniatura para não extrair conjuntos de dados gigantes da rede.

Como um conjunto de dados, usaremos habrastatistics com comentários de usuários para 2019, que estão disponíveis ao público graças a um usuário trabalhador:
conjunto de dados

Como base de informação, será utilizado o artigo traduzido anteriormente da Habr, no qual muitas coisas interessantes são misturadas.

Em vez de se juntar


O conjunto de dados de hastastatistics é considerado pequeno, embora ocupe 288 MB e consista em 448.533 linhas.
Claro, você pode encontrar mais dados, mas, para não pendurar o carro, vamos nos debruçar sobre ele.

Para conveniência das operações, adicionaremos (basta escrever a primeira linha do arquivo) os nomes das colunas:

a,b,c,d 

Agora, se você carregar diretamente o conjunto de dados no pandas e verificar quanta memória ele 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')) 

veja que ele "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 

Também mostra que estamos lidando com colunas que contêm dados do tipo objeto.
Portanto, de acordo com o artigo , para colunas, é necessário focar na otimização calculada para o objeto. Para todas as colunas, exceto uma.

A coluna b contém datas e, para conveniência de mais cálculos e clareza, é melhor enviá-las ao índice do conjunto de dados. Para fazer isso, altere o código usado ao ler o conjunto de dados:

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

Agora, as datas são lidas, pois o índice do conjunto de dados e o consumo de memória são ligeiramente reduzidos:

 memory usage: 407.0 MB 

Agora, otimizamos os dados no próprio conjunto de dados fora das colunas e indexamos


A otimização é chamada: “Otimização do armazenamento de dados de tipos de objetos usando variáveis ​​categóricas”.

Se traduzido para o russo, precisamos combinar os dados nas colunas por categoria, onde for eficaz.

Para determinar a eficácia, você precisa saber o número de valores exclusivos nas colunas e, se for menor que 50% do número total de valores na coluna, a combinação dos valores na categoria será efetiva.

Vejamos o conjunto de dados:

 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 

* coluna com datas no índice e não exibida

Como você pode ver, na linha exclusiva, nas colunas a e c, mesclando-se eficientemente em categorias. Para a coluna a, são 25100 usuários (obviamente menores que 448533), para os valores c - 185 da escala com "+" e "-" (também significativamente menores que 448533).

Otimizamos as colunas:

 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 entender quanta memória é usada por conveniência, apresentamos uma função:

 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) 

E verifique se a otimização foi eficaz:

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

Como você pode ver, foi recebido um ganho de outros 50 MB.

Agora, tendo entendido que a otimização se beneficiou (acontece e vice-versa), definiremos os parâmetros do conjunto de dados ao ler, a fim de levar em conta imediatamente os dados com os quais estamos lidando:

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

Desejamos que você trabalhe rapidamente com conjuntos de dados!

O código para download está aqui .

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


All Articles