Histogramas com Matplotlib em Python — Guia Completo
Aprenda a criar e personalizar histogramas em Python com Matplotlib. Cobre bins, densidade, KDE, histogramas cumulativos, empilhados e exportação.
A função hist() do Matplotlib torna simples visualizar como um conjunto de dados está distribuído ao longo de um intervalo numérico. Este capítulo cobre tudo, desde um primeiro histograma mínimo até técnicas práticas que você usará em projetos reais: escolher o número certo de bins, plotar densidade em vez de contagens brutas, sobrepor uma curva KDE, comparar múltiplas distribuições e salvar o resultado em um arquivo.
Antes de começar, certifique-se de que o Matplotlib e o NumPy estão instalados:
pip install matplotlib numpySe você é novo na biblioteca, consulte primeiro os capítulos Introdução ao Matplotlib e Primeiros Passos.
O que é um Histograma?
Um histograma divide uma variável numérica contínua em intervalos de igual tamanho chamados bins e desenha uma barra para cada bin cuja altura é igual ao número de observações que caem naquele intervalo. Ao contrário de um gráfico de barras, que compara categorias discretas, um histograma revela a forma de uma distribuição — se ela é simétrica, assimétrica, bimodal ou possui valores atípicos (outliers).
Use um histograma quando quiser responder perguntas como:
- Onde a maior parte dos dados está concentrada?
- A distribuição é aproximadamente normal ou é assimétrica?
- Existem lacunas ou múltiplos picos (dados bimodais)?
- Existem valores atípicos (outliers) distantes do grosso dos dados?
Criando um Histograma Básico
Passe um array unidimensional ou lista para plt.hist() e o Matplotlib escolhe automaticamente a contagem de bins:
import matplotlib.pyplot as plt
import numpy as np
# Reproducible example: 1 000 values from a normal distribution
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data)
plt.title('Basic Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()plt.tight_layout() evita que os rótulos dos eixos sejam cortados — um bom hábito antes de cada chamada a show() ou savefig().
Escolhendo o Número de Bins
O parâmetro bins é o ajuste mais importante de um histograma. Poucos bins escondem a estrutura; muitos bins criam ruído.
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
for ax, n_bins in zip(axes, [5, 30, 100]):
ax.hist(data, bins=n_bins, color='steelblue', edgecolor='white')
ax.set_title(f'bins={n_bins}')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
plt.suptitle('Effect of Bin Count', y=1.02)
plt.tight_layout()
plt.show()Diretrizes práticas:
- 5 a 10 bins — útil para conjuntos de dados muito pequenos (n < 50) ou visões gerais rápidas.
- 20 a 50 bins — bom padrão para a maioria dos conjuntos de dados (n = 100–10 000).
- 50 a 100+ bins — adequado para grandes conjuntos de dados (n > 10 000) onde a estrutura fina importa.
- Passe uma regra em string em vez de um número:
bins='auto',bins='fd'(Freedman–Diaconis) oubins='sturges'— o Matplotlib delega paranp.histogram_bin_edges()do NumPy.
Você também pode passar uma lista explícita de bordas de bin para espaçamento não uniforme:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.exponential(scale=2, size=1000)
# Finer bins near 0, coarser bins in the tail
edges = [0, 0.5, 1, 1.5, 2, 3, 4, 6, 8, 12]
plt.hist(data, bins=edges, color='darkorange', edgecolor='white')
plt.title('Custom Bin Edges (Exponential Data)')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()Personalizando a Aparência
Cor, Transparência e Borda
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=5, scale=1.5, size=800)
plt.hist(
data,
bins=30,
color='steelblue',
edgecolor='white', # thin white line between bars
linewidth=0.5,
alpha=0.85, # slight transparency
)
plt.title('Styled Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()alpha (0 = totalmente transparente, 1 = totalmente opaco) é especialmente útil ao sobrepor múltiplos histogramas para que as barras não se ocultem mutuamente.
Removendo Elementos Visuais Desnecessários
Remover as bordas superior e direita deixa o histograma com uma aparência mais limpa:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
fig, ax = plt.subplots(figsize=(8, 4))
ax.hist(data, bins=30, color='cornflowerblue', edgecolor='white')
ax.set_title('Clean Histogram')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.tight_layout()
plt.show()Histogramas de Densidade
Por padrão, hist() exibe contagens brutas no eixo y. Passe density=True para normalizar o eixo y de forma que a área total de todas as barras seja igual a 1. Isso transforma o histograma em uma estimativa de densidade de probabilidade, facilitando a comparação de conjuntos de dados de tamanhos diferentes.
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data, bins=30, density=True, color='mediumseagreen', edgecolor='white')
plt.title('Density Histogram')
plt.xlabel('Value')
plt.ylabel('Probability Density')
plt.tight_layout()
plt.show()Observação: os valores do eixo y são densidades, não probabilidades. Multiplique uma densidade pela largura do bin para obter a probabilidade daquele bin.
Sobrepondo uma Curva KDE
Uma estimativa de densidade de kernel (KDE) é uma curva suave que aproxima a distribuição de probabilidade subjacente. Sobrepô-la a um histograma de densidade fornece uma imagem intuitiva da forma da distribuição. Use scipy.stats.gaussian_kde para calculá-la:
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
fig, ax = plt.subplots(figsize=(8, 4))
# Density histogram
ax.hist(data, bins=30, density=True,
color='steelblue', edgecolor='white', alpha=0.6, label='Histogram')
# KDE curve
xs = np.linspace(data.min(), data.max(), 300)
kde = gaussian_kde(data)
ax.plot(xs, kde(xs), color='navy', linewidth=2, label='KDE')
ax.set_title('Histogram with KDE Overlay')
ax.set_xlabel('Value')
ax.set_ylabel('Probability Density')
ax.legend()
plt.tight_layout()
plt.show()Instale o SciPy se ainda não estiver disponível:
pip install scipyComparando Múltiplas Distribuições
Para comparar duas ou mais distribuições nos mesmos eixos, chame hist() várias vezes e use alpha para manter as barras semitransparentes. Defina os mesmos bins para ambas para que as larguras das barras sejam comparáveis:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
group_a = rng.normal(loc=0, scale=1, size=500)
group_b = rng.normal(loc=2, scale=1.5, size=500)
shared_bins = np.linspace(-5, 8, 40)
plt.hist(group_a, bins=shared_bins, alpha=0.6, color='steelblue', label='Group A')
plt.hist(group_b, bins=shared_bins, alpha=0.6, color='darkorange', label='Group B')
plt.title('Overlapping Histograms')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.legend()
plt.tight_layout()
plt.show()Definir shared_bins via np.linspace() garante que ambos os histogramas usem bordas de bin idênticas e que suas barras se alinhem visualmente.
Histogramas Lado a Lado (Empilhados)
Quando a sobreposição dificulta a leitura das distribuições individuais, use plt.subplots() para colocá-las lado a lado:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
group_a = rng.normal(loc=0, scale=1, size=500)
group_b = rng.normal(loc=2, scale=1.5, size=500)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4), sharey=True)
ax1.hist(group_a, bins=30, color='steelblue', edgecolor='white')
ax1.set_title('Group A')
ax1.set_xlabel('Value')
ax1.set_ylabel('Frequency')
ax2.hist(group_b, bins=30, color='darkorange', edgecolor='white')
ax2.set_title('Group B')
ax2.set_xlabel('Value')
plt.suptitle('Side-by-Side Histograms')
plt.tight_layout()
plt.show()sharey=True bloqueia ambos os subgráficos na mesma escala do eixo y para que as alturas das barras sejam diretamente comparáveis. Consulte o capítulo Subgráficos do Matplotlib para mais opções de layout.
Histogramas Cumulativos
Passe cumulative=True para desenhar um histograma onde cada barra representa a contagem total de observações até e incluindo aquele bin. Isso é útil para responder perguntas como "que fração dos valores está abaixo de X?":
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data, bins=30, cumulative=True, density=True,
color='mediumpurple', edgecolor='white')
plt.title('Cumulative Density Histogram')
plt.xlabel('Value')
plt.ylabel('Cumulative Probability')
plt.tight_layout()
plt.show()Combinado com density=True, o histograma cumulativo torna-se uma aproximação por função degrau da CDF empírica (função de distribuição cumulativa). O eixo y vai de 0 a 1.
Orientação do Histograma
Passe orientation='horizontal' para desenhar barras se estendendo para a esquerda a partir do eixo y. Essa raramente é a escolha padrão, mas espelha o layout dos gráficos de distribuição marginal de um gráfico de dispersão:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=500)
plt.hist(data, bins=20, orientation='horizontal',
color='tomato', edgecolor='white')
plt.title('Horizontal Histogram')
plt.ylabel('Value')
plt.xlabel('Frequency')
plt.tight_layout()
plt.show()Salvando um Histograma em Arquivo
Use plt.savefig() antes de plt.show() (ou em seu lugar). Especifique o formato pela extensão do arquivo:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data, bins=30, color='steelblue', edgecolor='white')
plt.title('Distribution of Sample Data')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.savefig('histogram.png', dpi=150) # raster, good for web
plt.savefig('histogram.pdf') # vector, good for print/publication
plt.show()Formatos comuns: png, pdf, svg, eps. Use svg ou pdf quando precisar de uma imagem escalável com qualidade para impressão.
Parâmetros Principais de hist() — Referência Rápida
| Parâmetro | Tipo | Descrição |
|---|---|---|
bins | int, lista ou string | Número de bins, bordas explícitas ou nome de regra ('auto', 'fd', 'sturges') |
density | boolean | Normaliza para que a área total = 1 (densidade de probabilidade) |
cumulative | boolean | Cada barra mostra a contagem/densidade cumulativa até aquele bin |
orientation | string | 'vertical' (padrão) ou 'horizontal' |
color | string | Cor de preenchimento das barras |
edgecolor | string | Cor da borda das barras; 'white' fornece um separador limpo |
alpha | float 0–1 | Transparência; defina abaixo de 1 ao sobrepor histogramas |
label | string | Rótulo da legenda para este histograma |
histtype | string | 'bar' (padrão), 'step', 'stepfilled' |
range | (min, max) | Recorta os dados para este intervalo antes da divisão em bins |
Erros Comuns
- Sementes aleatórias.
np.random.randn()produz valores diferentes a cada execução. Usenp.random.default_rng(seed)para exemplos reproduzíveis. densityvsnormed. O antigo parâmetronormed=Truefoi removido no Matplotlib 3.x. Use sempredensity=True.- Comparando histogramas com tamanhos de amostra diferentes. Barras de frequência bruta não são comparáveis quando os tamanhos dos grupos diferem — use
density=Truepara normalizar ambos. - Dados inteiros discretos. Para inteiros (por exemplo, lançamentos de dados, avaliações em pesquisas), defina as bordas dos bins em meios inteiros —
bins=[0.5, 1.5, 2.5, ..., 6.5]— para que cada inteiro caia exatamente em um bin sem ambiguidade de borda. plt.show()limpa a figura. Se você chamarshow()e depoissavefig(), obterá um arquivo em branco. Sempre chamesavefig()antes deshow().
Capítulos Relacionados
- Introdução ao Matplotlib — visão geral da biblioteca e instalação
- Primeiros Passos com Matplotlib — passo a passo do primeiro gráfico
- Gráficos de Barras com Matplotlib — comparando categorias discretas
- Gráficos de Dispersão com Matplotlib — relações entre duas variáveis
- Gráficos de Pizza com Matplotlib — proporções de parte para o todo
- Rótulos no Matplotlib — rótulos de eixos, títulos e anotações
- Subgráficos no Matplotlib — múltiplos gráficos em uma figura
- Distribuição de Dados — fundamentos estatísticos sobre distribuições