GroupBy & Agregação
O groupby do pandas implementa split-apply-combine: particiona linhas por chaves, executa uma função por grupo e junta os resultados em um resumo ou frame transformado.
Receita
Cartão de referência rápida - pronto para copiar e colar.
import pandas as pd
summary = (
df.groupby("region", observed=True)["revenue"]
.agg(total="sum", avg="mean", n="count")
.reset_index()
)
pivot = pd.pivot_table(df, index="month", columns="region", values="revenue", aggfunc="sum")Quando usar isso:
- Agrupamentos regionais ou de produtos em tabelas de fatos
- Métricas de janela que precisam de estatísticas por grupo
- Pivotação de dados longos para layouts de relatórios amplos
- Engenharia de features (médias de nível de grupo para ML)
Exemplo de Trabalho
import pandas as pd
sales = pd.DataFrame(
{
"region": pd.Categorical(["East", "West", "East", "West", "East"]),
"month": ["2025-01", "2025-01", "2025-02", "2025-02", "2025-02"],
"revenue": [120.0, 340.0, 150.0, 280.0, 130.0],
"units": [10, 25, 12, 20, 11],
}
)
# Agregação de múltiplas métricas
by_region = (
sales.groupby("region", observed=True)
.agg(revenue_total=("revenue", "sum"), units_avg=("units", "mean"))
.reset_index()
)
# Compartilhamento por linha do total regional (transform mantém a contagem de linhas)
sales = sales.copy()
sales["share"] = sales.groupby("region", observed=True)["revenue"].transform(
lambda s: s / s.sum()
)
# Pivot para relatórios
pivot = pd.pivot_table(
sales,
index="month",
columns="region",
values="revenue",
aggfunc="sum",
fill_value=0,
observed=True,
)
print(by_region)
print(sales[["region", "revenue", "share"]])
print(pivot)O que isso demonstra:
- Agregação nomeada com
.agg(col=(field, func)) transformpara frações de grupo em nível de linhapivot_tablecomfill_valuepara meses esparsosobserved=Trueem chaves categóricas
Mergulho Profundo
Como Funciona
- Split: Hash ou ordena linhas por chaves de grupo.
- Apply: Executa redução (
sum,mean) ou transformação (rank,fillna). - Combine: Empilha resultados em Series/DataFrame com um MultiIndex ou colunas planas.
as_index=False(padrão do pandas 2.x em muitas APIs) retorna chaves como colunas.
agg vs transform vs apply
| Método | Linhas de saída | Uso |
|---|---|---|
agg | Uma por grupo | Resumos |
transform | Igual à entrada | Estatísticas de grupo por linha |
apply | Varia | Lógica Python personalizada (mais lenta) |
Notas Python
import pandas as pd
# Múltiplas chaves
df.groupby(["region", "month"], observed=True)["revenue"].sum()
# Filtrar grupos por condição agregada
df.groupby("region").filter(lambda g: g["revenue"].sum() > 500)Armadilhas
- Incluindo NA nas chaves de grupo -
dropna=Falsemantém grupos NaN; muitas vezes acidental. Correção: Padrãodropna=Trueou limpe as chaves primeiro. - Níveis categóricos não observados - regiões vazias aparecem sem
observed=True. Correção: passeobserved=Trueno pandas 2.x groupby/pivot. applyretornando formas inconsistentes - quebra a etapa de combine. Correção: prefiraagg/transformintegrados; vetorize a lógica personalizada.- Chaves duplicadas no Pivot - múltiplas linhas por (mês, região) precisam de
aggfunc. Correção: escolha explicitamentesum,meanoufirst. - Classificar a saída do groupby - índice não classificado torna os relatórios difíceis de ler. Correção:
.sort_values("revenue_total", ascending=False).
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
Polars group_by | Agregações preguiçosas mais rápidas em dados grandes | Pequenos frames onde o pandas já está carregado |
| DuckDB SQL | Junções complexas + agregações em uma única consulta | Resumos simples de uma tabela |
pd.crosstab | Contagens de frequência de dois fatores | Somas de receita numérica |
NumPy bincount | Somas de buckets inteiros em dados 1-D | Múltiplas colunas e tratamento de NA |
FAQs
O que é observed=True?
- Limita o groupby categórico às categorias presentes nos dados.
- Evita grupos vazios de níveis de categoria não utilizados.
Como conto valores distintos por grupo?
df.groupby("region")["customer_id"].nunique()Como obtenho o rank dentro do grupo?
df["rank"] = df.groupby("region")["revenue"].rank(ascending=False)Posso agregar múltiplas colunas de forma diferente?
df.groupby("region").agg({"revenue": "sum", "units": "max"})Por que o groupby é lento?
- O
applydo Python por grupo é o culpado usual. - Use
aggvetorizado, Polars ou DuckDB para milhões de linhas.
Como redefinir o índice após o groupby?
out = df.groupby("region").sum().reset_index()O que é agregação nomeada?
.agg(total=("revenue", "sum"))nomeia as colunas de saída diretamente.- Mais claro do que colunas MultiIndex de
.agg(["sum", "mean"]).
Como pivot_table e groupby diferem?
- Mesmo motor por baixo - pivot é um açúcar para layout amplo.
- Use pivot quando os consumidores esperam colunas por categoria.
Como lidar com grupos baseados em tempo?
df.groupby(pd.Grouper(key="date", freq="ME"))para buckets de fim de mês.- Garanta o dtype datetime e a consistência de fuso horário primeiro.
Posso fazer groupby e plotar em uma linha?
df.groupby("region")["revenue"].sum().plot(kind="bar")- Ordene os valores primeiro para gráficos legíveis.
Relacionados
- pandas Series & DataFrames - indexação
- Joins & Merges - enriquecer antes de agrupar
- Séries Temporais -
Groupereresample - Polars -
group_byrápido em escala
Versões da Pilha: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.