Realizo regularmente operações de pandas em quadros de dados com mais de 15 milhões de linhas e gostaria de ter acesso a um indicador de progresso para operações específicas.
Existe um indicador de progresso baseado em texto para operações de divisão de aplicação e combinação de pandas?
Por exemplo, em algo como:
df_users.groupby(['userID', 'requestDate']).apply(feature_rollup)
onde feature_rollup
é uma função um pouco envolvida que pega muitas colunas do DF e cria novas colunas de usuário por meio de vários métodos. Essas operações podem demorar um pouco para grandes quadros de dados, então eu gostaria de saber se é possível ter uma saída baseada em texto em um notebook iPython que me atualize sobre o progresso.
Até agora, tentei indicadores de progresso de loop canônico para Python, mas eles não interagem com os pandas de maneira significativa.
Espero que haja algo que eu tenha esquecido na biblioteca / documentação do pandas que permita conhecer o progresso de uma combinação de aplicar e dividir. Uma implementação simples talvez analise o número total de subconjuntos de quadros de dados nos quais a apply
função está funcionando e relate o progresso como a fração concluída desses subconjuntos.
Talvez isso seja algo que precise ser adicionado à biblioteca?
Respostas:
Devido à demanda popular,
tqdm
adicionou suporte parapandas
. Diferentemente das outras respostas, isso não deixará os pandas mais lentos para baixo - eis um exemplo paraDataFrameGroupBy.progress_apply
:Caso você esteja interessado em saber como isso funciona (e como modificá-lo para seus próprios retornos de chamada), veja os exemplos no github , a documentação completa sobre o pypi ou importe o módulo e execute-o
help(tqdm)
.EDITAR
Para responder diretamente à pergunta original, substitua:
com:
Nota: tqdm <= v4.8 : Para versões do tqdm abaixo de 4.8, em vez de
tqdm.pandas()
você precisar:fonte
tqdm
foi realmente criado para iterables apenas simples originalmente:from tqdm import tqdm; for i in tqdm( range(int(1e8)) ): pass
O apoio pandas foi um hack recente eu fiz :)from tqdm import tqdm_notebook; tqdm_notebook().pandas(*args, **kwargs)
vemos aquitqdm
v5, que torna as coisas mais modularizadas.Ajustar a resposta de Jeff (e ter isso como uma função reutilizável).
Nota: aplique as atualizações de porcentagem de progresso em linha . Se sua função persistir, isso não funcionará.
Como de costume, você pode adicionar isso ao seu grupo por objetos como um método:
Como mencionado nos comentários, esse não é um recurso que os principais pandas estariam interessados em implementar. Mas o python permite que você os crie para muitos objetos / métodos do pandas (isso seria um pouco de trabalho ... embora você deva ser capaz de generalizar essa abordagem).
fonte
Caso você precise de suporte para como usar isso em um notebook Jupyter / ipython, como eu fiz, aqui está um guia e uma fonte úteis para o artigo relevante :
Observe o sublinhado na instrução de importação para
_tqdm_notebook
. Como o artigo referenciado menciona, o desenvolvimento está no estágio beta tardio.fonte
Para quem deseja aplicar o tqdm em seu código de aplicação de pandas paralelos personalizado.
(Tentei algumas das bibliotecas para paralelização ao longo dos anos, mas nunca encontrei uma solução 100% de paralelização, principalmente para a função de aplicação, e sempre tive que voltar para o meu código "manual".)
df_multi_core - este é o que você chama. Aceita:
_df_split - esta é uma função auxiliar interna que deve ser posicionada globalmente para o módulo em execução (Pool.map é "dependente de posicionamento"), caso contrário, eu a localizaria internamente.
aqui está o código da minha essência (vou adicionar mais testes de função de pandas lá):
Abaixo está um código de teste para uma aplicação paralela com tqdm "progress_apply".
Na saída, você pode ver 1 barra de progresso para execução sem paralelização e barras de progresso por núcleo ao executar com paralelização. Há um pequeno hickup e, às vezes, o restante dos núcleos aparece de uma só vez, mas mesmo assim acho útil, pois você obtém as estatísticas de progresso por núcleo (ele / s e total de registros, por ex)
Obrigado @abcdaa por esta ótima biblioteca!
fonte
try: splits = np.array_split(df[subset], njobs) except ValueError: splits = np.array_split(df, njobs)
devido à exceção KeyError em vez de ValueError, altere para Exception para lidar com todos os casos.Você pode fazer isso facilmente com um decorador
basta usar a função modified_ (e altere quando quiser imprimir)
fonte
logged_apply(g, func)
função, na qual você tenha acesso à ordem e possa registrar desde o início.Eu mudei a resposta de Jeff , para incluir um total, para que você possa acompanhar o progresso e uma variável para apenas imprimir cada X iterações (isso realmente melhora o desempenho por um monte, se o "print_at" é razoavelmente elevado)
a função clear_output () é de
se não no IPython, a resposta de Andy Hayden faz isso sem ele
fonte