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!