Histograma Matplotlib: O guia completo de plt.hist() em Python
Updated on
Voce tem um conjunto de dados com milhares de valores numericos -- idades, notas de testes, tempos de resposta, leituras de sensores -- e precisa entender como esses valores estao distribuidos. Estao agrupados em torno de um ponto central? Enviesados para um lado? Seguem uma distribuicao normal? Um grafico de dispersao nao vai ajudar. Um grafico de barras e projetado para categorias, nao para dados continuos. O que voce precisa e de um histograma, e em Python, matplotlib.pyplot.hist() e a forma padrao de construir um.
O problema e que plt.hist() tem mais de uma duzia de parametros, e a saida padrao frequentemente parece simples ou enganosa. Escolher o numero errado de bins pode esconder padroes importantes nos seus dados. Comparar multiplas distribuicoes em um unico grafico requer conhecer a combinacao certa de opcoes. Este guia cobre cada parametro importante, com exemplos de codigo funcionais que voce pode copiar diretamente para seu notebook ou script.
O que e um histograma e quando voce deve usar um?
Um histograma divide um intervalo de valores numericos em intervalos de largura igual chamados bins e conta quantos pontos de dados caem em cada bin. O eixo x mostra o intervalo de valores, e o eixo y mostra a frequencia (contagem) ou densidade para cada bin. Diferente de um grafico de barras, que exibe dados categoricos, um histograma representa a distribuicao de dados numericos continuos.
Use um histograma quando precisar:
- Ver a forma de uma distribuicao (normal, enviesada, bimodal, uniforme)
- Identificar valores atipicos ou lacunas nos dados
- Comparar a dispersao de valores entre grupos
- Decidir transformacoes de dados antes da modelagem
Sintaxe basica de plt.hist()
O histograma mais simples requer apenas um argumento: o array de dados.
import matplotlib.pyplot as plt
import numpy as np
# Generate 1000 normally distributed values
np.random.seed(42)
data = np.random.normal(loc=50, scale=15, size=1000)
plt.hist(data)
plt.title('Basic Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()Por padrao, matplotlib divide os dados em 10 bins. A funcao retorna tres objetos: as contagens dos bins, as bordas dos bins e os objetos patch (os retangulos desenhados). Cobriremos esses valores de retorno em detalhes mais adiante.
Assinatura completa
plt.hist(x, bins=None, range=None, density=False, weights=None,
cumulative=False, bottom=None, histtype='bar', align='mid',
orientation='vertical', rwidth=None, log=False, color=None,
label=None, stacked=False, edgecolor=None, alpha=None)Controlando bins
O parametro bins e a configuracao mais importante em um histograma. Poucos bins escondem padroes. Muitos bins criam ruido.
Definindo um numero fixo de bins
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
axes[0].hist(data, bins=5, edgecolor='black')
axes[0].set_title('5 Bins')
axes[1].hist(data, bins=30, edgecolor='black')
axes[1].set_title('30 Bins')
axes[2].hist(data, bins=100, edgecolor='black')
axes[2].set_title('100 Bins')
plt.tight_layout()
plt.show()Com 5 bins, voce ve apenas uma forma grosseira. Com 100 bins, tamanhos de amostra pequenos por bin introduzem ruido visual. Para este conjunto de dados de 1.000 pontos, 30 bins produz uma imagem clara da distribuicao normal.
Bordas de bins personalizadas
Passe uma sequencia para bins para definir limites exatos:
custom_edges = [0, 20, 35, 50, 65, 80, 100]
plt.hist(data, bins=custom_edges, edgecolor='black', color='steelblue')
plt.title('Histogram with Custom Bin Edges')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()Isso e util quando seus dados tem limiares significativos -- notas por letras, faixas etarias ou niveis de desempenho.
Algoritmos automaticos de bins
Matplotlib suporta varios algoritmos que calculam o numero ideal de bins com base nas caracteristicas dos dados:
| Algoritmo | Valor de bins= | Metodo | Melhor para |
|---|---|---|---|
| Sturges | 'sturges' | 1 + log2(n) | Conjuntos de dados pequenos, aproximadamente normais |
| Scott | 'scott' | Baseado no desvio padrao e n | Dados normais ou quase normais |
| Freedman-Diaconis | 'fd' | Baseado no IQR e n | Robusto a valores atipicos |
| Raiz quadrada | 'sqrt' | sqrt(n) | Estimativa rapida aproximada |
| Auto | 'auto' | Maximo de Sturges e FD | Padrao de uso geral |
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
for ax, method in zip(axes, ['sturges', 'scott', 'fd']):
ax.hist(data, bins=method, edgecolor='black', color='#4C72B0')
ax.set_title(f'bins="{method}"')
plt.tight_layout()
plt.show()Para a maioria dos casos, bins='auto' e um bom ponto de partida. Mude para 'fd' quando seus dados contiverem valores atipicos, pois ele usa o intervalo interquartil em vez do desvio padrao.
Histogramas normalizados e de densidade
Por padrao, o eixo y mostra contagens brutas. Defina density=True para normalizar o histograma de modo que a area total sob as barras seja igual a 1. Isso converte o eixo y de frequencia para densidade de probabilidade.
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].hist(data, bins=30, edgecolor='black', color='#55A868')
axes[0].set_title('Frequency (default)')
axes[0].set_ylabel('Count')
axes[1].hist(data, bins=30, edgecolor='black', color='#C44E52', density=True)
axes[1].set_title('Density (density=True)')
axes[1].set_ylabel('Probability Density')
plt.tight_layout()
plt.show()A normalizacao por densidade e essencial quando voce quer sobrepor uma curva de distribuicao teorica ou comparar conjuntos de dados de tamanhos diferentes:
from scipy import stats
plt.hist(data, bins=30, density=True, edgecolor='black', color='#55A868', alpha=0.7)
# Overlay the theoretical normal curve
x_range = np.linspace(data.min(), data.max(), 200)
plt.plot(x_range, stats.norm.pdf(x_range, loc=50, scale=15), 'r-', linewidth=2, label='Normal PDF')
plt.legend()
plt.title('Density Histogram with Normal Curve Overlay')
plt.show()Personalizando a aparencia
Cor, cor da borda e transparencia
plt.hist(data, bins=30, color='#4C72B0', edgecolor='white', alpha=0.85)
plt.title('Styled Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()Tipos de histograma
O parametro histtype altera o estilo visual:
Valor de histtype | Descricao |
|---|---|
'bar' | Barras preenchidas tradicionais (padrao) |
'barstacked' | Barras empilhadas para multiplos conjuntos de dados |
'step' | Contorno de linha nao preenchido |
'stepfilled' | Area preenchida com contorno em degraus |
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
types = ['bar', 'barstacked', 'step', 'stepfilled']
for ax, ht in zip(axes.flat, types):
ax.hist(data, bins=30, histtype=ht, edgecolor='black', color='#4C72B0')
ax.set_title(f'histtype="{ht}"')
plt.tight_layout()
plt.show()O tipo 'step' e particularmente util ao sobrepor multiplas distribuicoes, ja que contornos nao preenchidos nao se obscurecem mutuamente.
Multiplos histogramas em um grafico
Histogramas sobrepostos
Use alpha (transparencia) para sobrepor duas ou mais distribuicoes:
np.random.seed(42)
group_a = np.random.normal(loc=50, scale=10, size=800)
group_b = np.random.normal(loc=65, scale=12, size=800)
plt.hist(group_a, bins=30, alpha=0.6, color='#4C72B0', edgecolor='black', label='Group A')
plt.hist(group_b, bins=30, alpha=0.6, color='#C44E52', edgecolor='black', label='Group B')
plt.legend()
plt.title('Overlapping Histograms')
plt.xlabel('Score')
plt.ylabel('Frequency')
plt.show()Histogramas lado a lado
Passe uma lista de arrays para plota-los com barras agrupadas:
plt.hist([group_a, group_b], bins=20, color=['#4C72B0', '#C44E52'],
edgecolor='black', label=['Group A', 'Group B'])
plt.legend()
plt.title('Side-by-Side Histograms')
plt.xlabel('Score')
plt.ylabel('Frequency')
plt.show()Quando voce passa uma lista de arrays, matplotlib coloca as barras de cada conjunto de dados lado a lado dentro de cada bin.
Histogramas empilhados
Defina stacked=True para empilhar um conjunto de dados sobre outro. Isso mostra tanto as distribuicoes individuais quanto o total combinado.
np.random.seed(42)
freshmen = np.random.normal(loc=68, scale=8, size=500)
sophomores = np.random.normal(loc=72, scale=7, size=400)
juniors = np.random.normal(loc=75, scale=6, size=300)
plt.hist([freshmen, sophomores, juniors], bins=25, stacked=True,
color=['#4C72B0', '#55A868', '#C44E52'], edgecolor='black',
label=['Freshmen', 'Sophomores', 'Juniors'])
plt.legend()
plt.title('Stacked Histogram: Exam Scores by Class Year')
plt.xlabel('Score')
plt.ylabel('Frequency')
plt.show()Histogramas empilhados funcionam bem quando voce quer mostrar como subgrupos contribuem para uma distribuicao geral. No entanto, ficam dificeis de ler com mais de tres ou quatro grupos.
Histogramas cumulativos
Defina cumulative=True para mostrar como os valores se acumulam da esquerda para a direita. A ultima barra atinge a contagem total (ou 1,0 se density=True).
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].hist(data, bins=30, cumulative=True, edgecolor='black', color='#DD8452')
axes[0].set_title('Cumulative Histogram (Count)')
axes[0].set_ylabel('Cumulative Count')
axes[1].hist(data, bins=30, cumulative=True, density=True, edgecolor='black', color='#8172B3')
axes[1].set_title('Cumulative Histogram (Density)')
axes[1].set_ylabel('Cumulative Probability')
plt.tight_layout()
plt.show()Histogramas cumulativos sao uteis para responder perguntas como "Qual porcentagem dos valores esta abaixo de 60?" lendo diretamente do eixo y.
Histogramas horizontais
Defina orientation='horizontal' para inverter os eixos. Isso e util quando os rotulos de valores sao longos ou quando voce quer colocar o histograma ao lado de outro grafico vertical.
plt.hist(data, bins=30, orientation='horizontal', color='#64B5CD', edgecolor='black')
plt.title('Horizontal Histogram')
plt.xlabel('Frequency')
plt.ylabel('Value')
plt.show()Valores de retorno de plt.hist()
plt.hist() retorna tres valores que dao acesso programatico aos dados do histograma:
n, bin_edges, patches = plt.hist(data, bins=20, edgecolor='black', color='#4C72B0')
plt.show()
print(f"Bin counts (n): shape = {n.shape}, first 5 = {n[:5]}")
print(f"Bin edges: shape = {bin_edges.shape}, first 5 = {bin_edges[:5]}")
print(f"Patches: {len(patches)} Rectangle objects")| Valor de retorno | Tipo | Descricao |
|---|---|---|
n | ndarray | Contagem (ou densidade) para cada bin |
bin_edges | ndarray | Valores das bordas para cada bin (comprimento = len(n) + 1) |
patches | lista de Rectangles | Os objetos patch matplotlib para cada barra |
Voce pode usar patches para colorir barras individuais com base na sua altura ou posicao:
n, bin_edges, patches = plt.hist(data, bins=30, edgecolor='black')
# Color bars based on height
for count, patch in zip(n, patches):
if count > 50:
patch.set_facecolor('#C44E52')
else:
patch.set_facecolor('#4C72B0')
plt.title('Conditional Bar Coloring')
plt.show()Referencia de parametros comuns de plt.hist()
| Parametro | Tipo | Descricao | Padrao |
|---|---|---|---|
x | array-like | Dados de entrada | Obrigatorio |
bins | int, sequencia ou str | Numero de bins, bordas de bins ou nome do algoritmo | 10 |
range | tuple | Intervalo inferior e superior dos bins | (x.min(), x.max()) |
density | bool | Normalizar para que a area seja igual a 1 | False |
weights | array-like | Peso para cada ponto de dados | None |
cumulative | bool | Calcular histograma cumulativo | False |
histtype | str | 'bar', 'barstacked', 'step', 'stepfilled' | 'bar' |
orientation | str | 'vertical' ou 'horizontal' | 'vertical' |
color | color ou lista | Cor(es) da barra | None |
edgecolor | color | Cor da borda da barra | None |
alpha | float | Transparencia (0 a 1) | None |
label | str | Rotulo para a legenda | None |
stacked | bool | Empilhar multiplos conjuntos de dados | False |
log | bool | Eixo y logaritmico | False |
rwidth | float | Largura relativa das barras (0 a 1) | None |
bottom | array-like ou escalar | Linha de base para cada barra | 0 |
plt.hist() vs sns.histplot(): Quando usar qual
Se voce usa seaborn junto com matplotlib, pode se perguntar qual funcao de histograma usar. Aqui esta uma comparacao direta:
| Caracteristica | plt.hist() | sns.histplot() |
|---|---|---|
| Biblioteca | matplotlib | seaborn |
| Tipos de entrada | Array, lista, Series | Array, Series, coluna DataFrame |
| Sobreposicao KDE | Manual (scipy necessario) | Integrado (kde=True) |
| Estilo padrao | Minimo | Pronto para publicacao |
| Multiplos grupos | Passar lista de arrays | Parametro hue |
| Opcoes estatisticas | Contagem, densidade | Contagem, densidade, frequencia, probabilidade, porcentagem |
| Algoritmos de bins | sturges, scott, fd, sqrt, auto | auto, fd, doane, scott, stone, rice, sturges, sqrt |
| Escala logaritmica | log=True | log_scale=True |
| Eixo categorico | Nao suportado | Suportado via hue |
| Desempenho (grandes dados) | Mais rapido | Ligeiramente mais lento |
| Profundidade de personalizacao | API completa matplotlib | API seaborn + matplotlib |
Use plt.hist() quando precisar de controle total sobre cada elemento visual, ao trabalhar com subplots, ou quando seaborn nao estiver disponivel. Use sns.histplot() quando quiser sobreposicoes KDE, estilo padrao mais limpo, ou precisar dividir dados por uma variavel categorica com codigo minimo.
Crie histogramas interativos com PyGWalker
Histogramas estaticos sao otimos para relatorios e scripts, mas durante a analise exploratoria de dados voce frequentemente precisa mudar bins, filtrar subconjuntos e alternar entre tipos de graficos rapidamente. PyGWalker (opens in a new tab) e uma biblioteca Python de codigo aberto que transforma qualquer DataFrame pandas ou polars em uma interface de visualizacao interativa de arrastar e soltar diretamente dentro do Jupyter Notebook -- sem necessidade de codigo frontend.
pip install pygwalkerimport pandas as pd
import pygwalker as pyg
# Load your dataset into a DataFrame
df = pd.DataFrame({
'score': np.random.normal(70, 12, 2000),
'group': np.random.choice(['A', 'B', 'C'], 2000)
})
# Launch the interactive UI
walker = pyg.walk(df)Uma vez que a interface abra, arraste score para o eixo x e o PyGWalker gera automaticamente um histograma. Voce pode ajustar o tamanho do bin, dividir por group usando codificacao de cor, mudar para o modo de densidade e exportar o grafico resultante -- tudo sem escrever codigo adicional. Isso e especialmente util quando voce precisa explorar varias variaveis rapidamente antes de escrever o codigo final matplotlib para um relatorio.
Perguntas frequentes
Como escolho o numero certo de bins para um histograma matplotlib?
Comece com bins='auto', que usa o maximo dos metodos Sturges e Freedman-Diaconis. Para dados com valores atipicos, use bins='fd'. Para conjuntos de dados pequenos (menos de 200 pontos), bins='sturges' funciona bem. Voce tambem pode passar um inteiro e ajustar visualmente: aumente o numero se a distribuicao parecer muito suave, diminua se as barras parecerem ruidosas.
Qual e a diferenca entre density=True e cumulative=True em plt.hist()?
density=True normaliza o histograma para que a area total sob todas as barras seja igual a 1, convertendo o eixo y para densidade de probabilidade. cumulative=True faz cada barra representar a soma de todas as barras anteriores mais ela mesma. Voce pode combinar ambos: density=True, cumulative=True produz uma funcao de distribuicao cumulativa onde a ultima barra atinge 1,0.
Como sobrepor dois histogramas em matplotlib?
Chame plt.hist() duas vezes com o mesmo valor de bins e defina alpha para um valor menor que 1 (por exemplo, 0,5 ou 0,6) para que ambas distribuicoes permanecam visiveis. Adicione label a cada chamada e finalize com plt.legend(). Usar histtype='step' como alternativa evita completamente a necessidade de transparencia, ja que desenha apenas contornos.
plt.hist() pode lidar com pandas Series e colunas de DataFrame diretamente?
Sim. plt.hist() aceita qualquer entrada tipo array, incluindo pandas Series. Voce pode passar df['column_name'] diretamente. Para plotar a partir de um DataFrame usando o metodo integrado do pandas, use df['column_name'].plot.hist(bins=30), que usa matplotlib internamente.
Como salvo um histograma matplotlib como arquivo de imagem?
Apos chamar plt.hist(), use plt.savefig('histogram.png', dpi=150, bbox_inches='tight') antes de plt.show(). O parametro bbox_inches='tight' evita que rotulos sejam cortados. Os formatos suportados incluem PNG, PDF, SVG e EPS.