Eu tenho um arquivo csv muito grande que abri no pandas da seguinte maneira ....
import pandas
df = pandas.read_csv('large_txt_file.txt')
Depois de fazer isso, meu uso de memória aumenta em 2 GB, o que é esperado porque este arquivo contém milhões de linhas. Meu problema surge quando preciso liberar essa memória. Eu corri ....
del df
No entanto, meu uso de memória não diminuiu. É esta a abordagem errada para liberar memória usada por um quadro de dados do pandas? Se for, qual é a maneira adequada?
gc
módulo e chamar,gc.collect()
mas ele pode não recuperar a memóriadel df
não é chamado diretamente após a criação do df certo? Acho que há referências ao df no momento em que você exclui o df. Portanto, ele não será excluído em vez disso, ele exclui o nome.df = ''
no final do seu código? Parece limpar a RAM usada pelo dataframe.Respostas:
Reduzir o uso de memória em Python é difícil, porque Python não libera memória de volta para o sistema operacional . Se você excluir objetos, a memória estará disponível para novos objetos Python, mas não será
free()
devolvida ao sistema ( veja esta questão ).Se você se limitar a matrizes numpy numéricas, elas serão liberadas, mas os objetos em caixas não.
Reduzindo o número de Dataframes
Python mantém nossa memória com marca d'água alta, mas podemos reduzir o número total de dataframes que criamos. Ao modificar seu dataframe, prefira
inplace=True
, para não criar cópias.Outra pegadinha comum é manter cópias de dataframes criados anteriormente em ipython:
Você pode corrigir isso digitando
%reset Out
para limpar seu histórico. Alternativamente, você pode ajustar quanto histórico o ipython mantémipython --cache-size=5
(o padrão é 1000).Reduzindo o tamanho do dataframe
Sempre que possível, evite usar tipos de objetos.
Os valores com um objeto dtype são encaixotados, o que significa que o array numpy contém apenas um ponteiro e você tem um objeto Python completo no heap para cada valor em seu dataframe. Isso inclui strings.
Enquanto o numpy suporta strings de tamanho fixo em arrays, o pandas não ( isso causa confusão ao usuário ). Isso pode fazer uma diferença significativa:
Você pode evitar o uso de colunas de string ou encontrar uma maneira de representar dados de string como números.
Se você tiver um dataframe que contém muitos valores repetidos (NaN é muito comum), você pode usar uma estrutura de dados esparsa para reduzir o uso de memória:
Visualizando o uso da memória
Você pode ver o uso de memória ( documentos ):
A partir do pandas 0.17.1, você também pode fazer
df.info(memory_usage='deep')
para ver o uso de memória, incluindo objetos.fonte
Conforme observado nos comentários, existem algumas coisas para tentar:
gc.collect
(@EdChum) pode limpar coisas, por exemplo. Pelo menos pela minha experiência, essas coisas às vezes funcionam e muitas vezes não.No entanto, há uma coisa que sempre funciona porque é feito no nível do sistema operacional, não no idioma.
Suponha que você tenha uma função que cria um grande DataFrame intermediário e retorna um resultado menor (que também pode ser um DataFrame):
Então, se você fizer algo como
Em seguida, a função é executada em um processo diferente . Quando esse processo é concluído, o SO retoma todos os recursos que usou. Não há realmente nada que Python, pandas, o coletor de lixo possam fazer para impedir isso.
fonte
with multiprocessing.Pool(1) as pool: result = pool.map(huge_intermediate_calc, [something])
que leva a fechar o pool uma vez feito.Isso resolve o problema de liberar a memória pra mim !!!
o quadro de dados será explicitamente definido como nulo
fonte
del df
não será excluído se houver qualquer referência adf
no momento da exclusão. Portanto, você precisa excluir todas as referências a eledel df
para liberar a memória.Portanto, todas as instâncias vinculadas a df devem ser excluídas para acionar a coleta de lixo.
Use objgragh para verificar qual está segurando os objetos.
fonte
Parece que há um problema com o glibc que afeta a alocação de memória no Pandas: https://github.com/pandas-dev/pandas/issues/2659
O patch monkey detalhado neste problema resolveu o problema para mim:
fonte