Skip to content
Tópicos
Matplotlib
Matplotlib Histogram: The Complete Guide to plt.hist() in Python

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:

AlgoritmoValor de bins=MetodoMelhor para
Sturges'sturges'1 + log2(n)Conjuntos de dados pequenos, aproximadamente normais
Scott'scott'Baseado no desvio padrao e nDados normais ou quase normais
Freedman-Diaconis'fd'Baseado no IQR e nRobusto a valores atipicos
Raiz quadrada'sqrt'sqrt(n)Estimativa rapida aproximada
Auto'auto'Maximo de Sturges e FDPadrao 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 histtypeDescricao
'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 retornoTipoDescricao
nndarrayContagem (ou densidade) para cada bin
bin_edgesndarrayValores das bordas para cada bin (comprimento = len(n) + 1)
patcheslista de RectanglesOs 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()

ParametroTipoDescricaoPadrao
xarray-likeDados de entradaObrigatorio
binsint, sequencia ou strNumero de bins, bordas de bins ou nome do algoritmo10
rangetupleIntervalo inferior e superior dos bins(x.min(), x.max())
densityboolNormalizar para que a area seja igual a 1False
weightsarray-likePeso para cada ponto de dadosNone
cumulativeboolCalcular histograma cumulativoFalse
histtypestr'bar', 'barstacked', 'step', 'stepfilled''bar'
orientationstr'vertical' ou 'horizontal''vertical'
colorcolor ou listaCor(es) da barraNone
edgecolorcolorCor da borda da barraNone
alphafloatTransparencia (0 a 1)None
labelstrRotulo para a legendaNone
stackedboolEmpilhar multiplos conjuntos de dadosFalse
logboolEixo y logaritmicoFalse
rwidthfloatLargura relativa das barras (0 a 1)None
bottomarray-like ou escalarLinha de base para cada barra0

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:

Caracteristicaplt.hist()sns.histplot()
Bibliotecamatplotlibseaborn
Tipos de entradaArray, lista, SeriesArray, Series, coluna DataFrame
Sobreposicao KDEManual (scipy necessario)Integrado (kde=True)
Estilo padraoMinimoPronto para publicacao
Multiplos gruposPassar lista de arraysParametro hue
Opcoes estatisticasContagem, densidadeContagem, densidade, frequencia, probabilidade, porcentagem
Algoritmos de binssturges, scott, fd, sqrt, autoauto, fd, doane, scott, stone, rice, sturges, sqrt
Escala logaritmicalog=Truelog_scale=True
Eixo categoricoNao suportadoSuportado via hue
Desempenho (grandes dados)Mais rapidoLigeiramente mais lento
Profundidade de personalizacaoAPI completa matplotlibAPI 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 pygwalker
import 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.

📚