Inteligência artificial, sem ruído.
Tutoriais7 min

7 passos para automatizar estatísticas descritivas com Python

Pare de escrever mean() e std() para cada coluna. Aprenda a automatizar estatísticas descritivas em Python com 7 ferramentas que geram tabelas prontas para publicação.

7 passos para automatizar estatísticas descritivas com Python

Toda análise de dados começa da mesma forma: você carrega um dataset e tenta entender o que há nele. Quantas linhas? Quais colunas são numéricas? Quanto está faltando? Alguma variável está extremamente distorcida? A maioria de nós responde essas perguntas copiando e colando os mesmos trechos de df.describe(), df.isna().sum() e df.groupby(...).agg(...) que já digitamos milhares de vezes.

Isso é esforço desperdiçado. O ecossistema Python hoje oferece ferramentas que levam você de um DataFrame bruto a uma tabela de resumo formatada e compartilhável em uma ou duas linhas — e outras desenvolvidas especificamente para produzir o tipo de “Tabela 1” que você vê em artigos científicos.

Este tutorial, baseado no artigo de Kanwal Mehreen no KDnuggets, percorre 7 passos para construir um pipeline repetível de estatísticas descritivas em Python. Usaremos o dataset Palmer Penguins ao longo do caminho — ele é pequeno, aberto e tem uma mistura realista de colunas numéricas e categóricas, valores ausentes reais e uma variável de agrupamento natural (species).

Pré-requisitos

ComponenteMínimoRecomendado
Python3.8+3.11+
Pandas1.5+2.2+
Pacotes adicionaisskimpy, tableonegreat-tables, fg-data-profiling
Conhecimento prévioPandas básicoEstatística descritiva
Requisitos para acompanhar o tutorial

Passo 1: Configurando o ambiente e carregando os dados

Instale os pacotes que usaremos:

pip install pandas seaborn skimpy tableone great-tables fg-data-profiling

Nota importante sobre o último pacote: a popular biblioteca de profiling foi renomeada mais de uma vez. Começou como pandas-profiling, virou ydata-profiling em 2023 e foi renomeada novamente para fg-data-profiling em abril de 2026. Para novos projetos, prefira fg-data-profiling.

Agora carregue os dados. O Seaborn inclui o dataset Penguins nativamente:

import pandas as pd
import seaborn as sns

df = sns.load_dataset("penguins")
print(df.shape)        # (344, 7)
print(df.dtypes)       # 3 categóricas + 4 numéricas
print(df.isna().sum()) # 2 ausentes em medidas, 11 em sex

O dataset tem sete colunas: três categóricas (species, island, sex) e quatro medições numéricas (bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g). As medições têm 2 valores ausentes cada, e sex tem 11.

Passo 2: Linha de base com df.describe()

O describe() do Pandas é o ponto de partida óbvio — é instantâneo e não requer instalação adicional:

df.describe().round(2)

O resultado mostra contagem, média, desvio padrão, mínimo, quartis e máximo para as 4 colunas numéricas. Útil, mas com pontos cegos importantes: ignora colunas categóricas, mostra contagem de valores não-nulos mas não a porcentagem de ausentes, e para no resumo de cinco números — sem assimetria, sem curtose, sem noção da forma da distribuição.

Passo 3: Expandindo o Pandas com include, .agg() e groupby

Para incluir categóricas no describe():

df.describe(include="all").round(2)

Isso adiciona unique, top e freq para colunas categóricas. Para mais controle, use .agg() com dicionário:

df.agg({
    "bill_length_mm": ["mean", "std", "skew"],
    "body_mass_g": ["mean", "std", "min", "max"]
}).round(2)

E para estatísticas por grupo:

df.groupby("species").agg({
    "bill_length_mm": ["mean", "std"],
    "body_mass_g": ["mean", "std"]
}).round(2)

Isso já cobre 80% dos casos de uso. Mas a formatação ainda é bruta — você precisa copiar, colar e ajustar manualmente para um relatório.

Passo 4: Resumos elegantes com skimpy

O skimpy gera tabelas de resumo limpas e prontas para publicação com uma única função:

from skimpy import skim
skim(df)

A saída inclui: tipo de dado, contagem, valores ausentes (contagem e %), média, desvio padrão, mínimo, máximo, e um mini-histograma inline no terminal para cada coluna numérica. Para categóricas, mostra contagem de categorias únicas e a categoria mais frequente.

O grande diferencial do skimpy é o mini-histograma inline — você identifica assimetria e outliers em um piscar de olhos, sem gerar gráficos separados.

Passo 5: Tabela 1 profissional com tableone

O tableone replica o padrão acadêmico da “Tabela 1” — a tabela de características basais da amostra que aparece em todo artigo científico:

from tableone import TableOne

table = TableOne(
    df,
    columns=["bill_length_mm", "bill_depth_mm",
             "flipper_length_mm", "body_mass_g"],
    categorical=["species", "island", "sex"],
    groupby="species",
    pval=True,
    missing=False
)
print(table.tabulate(tablefmt="grid"))

O tableone calcula automaticamente: média (DP) para variáveis contínuas, n (%) para categóricas, e valores-p para comparação entre grupos (ANOVA para contínuas, qui-quadrado para categóricas). Perfeito para papers e relatórios clínicos.

Passo 6: Tabelas formatadas em HTML com great-tables

O great-tables (do ecossistema Posit/RStudio) leva a formatação para outro nível, gerando tabelas HTML com estilo profissional:

from great_tables import GT

# Criar tabela de resumo por espécie
summary = df.groupby("species").agg(
    count=("body_mass_g", "count"),
    mean_mass=("body_mass_g", "mean"),
    sd_mass=("body_mass_g", "std"),
    mean_bill=("bill_length_mm", "mean"),
    sd_bill=("bill_length_mm", "std")
).reset_index()

gt = GT(summary)
gt.tab_header(title="Penguins: Resumo por Espécie")
gt.fmt_number(columns=["mean_mass", "sd_mass", "mean_bill", "sd_bill"], decimals=1)
gt.show()  # Renderiza HTML

O great-tables é ideal para incluir tabelas diretamente em dashboards Streamlit, relatórios Quarto ou notebooks Jupyter.

Passo 7: Perfil completo automatizado com fg-data-profiling

Para o relatório mais completo — uma página HTML interativa com tudo: correlações, distribuições, missing values, alerts — use o fg-data-profiling:

from fg_data_profiling import ProfileReport

profile = ProfileReport(df, title="Penguins Dataset - Profiling Report")
profile.to_file("penguins_report.html")

O relatório gerado inclui: visão geral do dataset, análise de cada variável (histograma, valores distintos, missing), correlações (Pearson, Spearman, Cramér’s V), alertas automáticos (alta cardinalidade, missing values, skewness, correlação alta) e amostra dos dados.

Tabela comparativa das ferramentas

FerramentaMelhor paraSaídaCurva de aprendizado
df.describe()Check rápido no consoleTextoZero
skimpyResumo visual no terminalTexto + histogramasBaixa
tableoneTabela 1 acadêmicaTexto formatadoMédia
great-tablesTabelas HTML profissionaisHTMLMédia
fg-data-profilingRelatório interativo completoHTMLBaixa
Comparação das ferramentas de estatística descritiva em Python

Pipeline completo em uma função

Juntando tudo em uma função reutilizável:

def descriptive_pipeline(df, groupby=None, output_dir="reports"):
    # Gera relatório completo de estatísticas descritivas
    import os

os.makedirs(output_dir, exist_ok=True)

# 1. Linha de base
print(“=== df.describe() ===”)
print(df.describe(include=”all”).round(2))

# 2. skimpy
from skimpy import skim
print(”
=== skimpy ===”)
skim(df)

# 3. tableone com grupo
if groupby:
from tableone import TableOne
num_cols = df.select_dtypes(“number”).columns.tolist()
cat_cols = df.select_dtypes([“object”, “category”]).columns.tolist()
t1 = TableOne(df, columns=num_cols, categorical=cat_cols,
groupby=groupby, pval=True)
t1.to_csv(f”{output_dir}/tableone.csv”)
print(f”
Tabela 1 salva em {output_dir}/tableone.csv”)

# 4. Relatório completo
from fg_data_profiling import ProfileReport
profile = ProfileReport(df, title=”Relatório Descritivo”)
profile.to_file(f”{output_dir}/report.html”)
print(f”Relatório salvo em {output_dir}/report.html”)

# Uso
descriptive_pipeline(df, groupby=”species”)

Troubleshooting

  • ❌ Erro ao instalar fg-data-profiling: o pacote foi renomeado recentemente. Tente pip install ydata-profiling como fallback (versão anterior, ainda funcional).
  • ❌ skimpy não mostra histogramas: verifique se seu terminal suporta Unicode. No Windows, use o novo Terminal ou PowerShell 7+.
  • ❌ tableone quebra com colunas não numéricas: o parâmetro columns deve conter apenas colunas numéricas. Use df.select_dtypes("number").columns para filtrar.
  • ❌ MemoryError com datasets grandes: o fg-data-profiling processa o dataset inteiro na memória. Para datasets > 1M de linhas, use ProfileReport(df.sample(100000)).
  • ❌ Valores-p do tableone dão NaN: ocorre quando um grupo tem variância zero ou tamanho muito pequeno. Verifique com df.groupby(grupo).size().

FAQ

Preciso de todas essas ferramentas? Não. Comece com df.describe() + skimpy para o dia a dia. Adicione tableone se publicar papers. Adicione fg-data-profiling para relatórios automáticos.

Qual a diferença entre skimpy e fg-data-profiling? Skimpy é rápido, textual e roda no terminal. fg-data-profiling gera um relatório HTML interativo completo — use quando precisar compartilhar resultados com não-técnicos.

Funciona com PySpark ou Polars? tableone e fg-data-profiling exigem Pandas. Para Polars, converta com .to_pandas(). Para PySpark, use summary() nativo.

Dá para automatizar isso em CI/CD? Sim. O pipeline pode rodar em GitHub Actions após cada atualização de dados, gerando relatórios como artifacts.

Preciso aprender great-tables se já uso matplotlib/seaborn? São propósitos diferentes. great-tables gera tabelas formatadas, não gráficos. Use junto com matplotlib para combinar visualizações e tabelas no mesmo relatório.


Descubra mais sobre noticiAI

Assine para receber nossas notícias mais recentes por e-mail.

R
Sobre o autorRedação Noticiai

Equipe editorial dedicada a explicar inteligência artificial com clareza, independência e contexto.