Olá pessoal,
Venho compartilhar uma experiência recente com operações de groupby()
no Pandas que estavam extremamente lentas — e como consegui resolver com uma simples mas poderosa transformação: converter a coluna categórica para o tipo Categorical
.
Problema inicial
Estava trabalhando com um DataFrame chamado emissoes_por_ano
e realizei algumas medições de tempo no Google Colab:
Tempos no google colab:
Operação | Tempo aproximado |
---|---|
emissoes_por_ano.groupby('Gás') | 0s |
emissoes_por_ano.groupby('Gás').groups (0s) | 0s |
emissoes_por_ano.groupby('Gás').get_group('CO2 (t)') | 1s |
emissoes_por_ano.groupby('Gás').sum() | +32 minutos (interrompi antes de terminar!) |
A última operação (groupby().sum()
) estava tão lenta que cheguei a pensar se havia algum erro no código ou no dataset.
Solução aplicada
Pesquisei maneiras de resolver a questão e encontrei uma otimização bem conhecida no mundo do Pandas: converter a coluna "Gás"
para o tipo Categorical
:
emissoes_por_ano["Gás"] = pd.Categorical(emissoes_por_ano["Gás"])
Essa linha faz uma mudança importante: ela transforma os valores repetidos da coluna "Gás"
(como 'CO2 (t)'
, 'CH4 (t)'
, etc.) em índices inteiros internos, mantendo uma tabela de rótulos únicos. Isso reduz o uso de memória e acelera comparações e agrupamentos.
Após essa conversão, executei novamente as mesmas operações:
Operação | Tempo aproximado |
---|---|
emissoes_por_ano.groupby('Gás', observed=True) | 0s |
emissoes_por_ano.groupby('Gás', observed=True).groups | 0s |
emissoes_por_ano.groupby('Gás', observed=True).get_group('CO2 (t)') | 0s |
emissoes_por_ano.groupby('Gás', observed=True)['Emissão'].sum() | 0s |
O resultado foi surpreendente: todas as operações passaram a ser executadas instantaneamente!
Por que isso funciona?
O que é pd.Categorical()
?
É uma estrutura do Pandas projetada para lidar com variáveis categóricas — isto é, colunas com poucos valores distintos repetidos, como:
"Gás"
→'CO2 (t)'
,'CH4 (t)'
, etc."Estado"
→'SP'
,'RJ'
,'MG'
, etc."Tipo de cliente"
→'Premium'
,'Básico'
, etc.
Vantagens:
- Menor consumo de memória
- Operações mais rápidas (comparação de inteiros é muito mais eficiente que strings)
- Melhor integração com groupby, merge e join
Dica extra: use observed=True
Ao usar groupby()
com colunas categóricas, recomendo sempre adicionar o parâmetro:
.groupby('Gás', observed=True)
Isso evita que o Pandas inclua categorias vazias nos resultados, o que também ajuda na performance e na clareza dos dados.
Comparação com R (factor
)
Se você vem do R, talvez já conheça o conceito de factor
. No Pandas, pd.Categorical
tem comportamento bastante semelhante:
Recurso | R (factor ) | Python (Categorical ) |
---|---|---|
Armazenamento | Inteiros + lista de níveis | Códigos + categorias |
Eficiência | Alta | Alta |
Ordenação | ordered=TRUE | ordered=True |
Funções básicas | levels() , relevel() | .cat.categories , .cat.reorder_categories() |
Então, se você já usou factor()
no R, pense em pd.Categorical()
como seu equivalente direto no Python.
Em resumo
Se você está enfrentando lentidão com groupby()
ou outras operações de agregação:
Considere converter suas colunas categóricas para Categorical
É uma das formas mais simples e eficazes de melhorar a performance do seu código em análise de dados com Pandas.
Abraço!