Pular para o conteúdo principal

Histogramas no Matplotlib

Aprenda sobre histogramas e como você pode usá-los para obter insights dos dados com a ajuda do matplotlib.
24 de abr. de 2024  · 8 min de leitura

Introdução

De acordo com a Wikipediaum histograma é uma representação gráfica precisa da distribuição de dados numéricos. É uma estimativa da distribuição de probabilidade de uma variável contínua (variável quantitativa) e foi introduzida pela primeira vez por Karl Pearson. É um tipo de gráfico de barras. Para construir um histograma, a primeira etapa é "classificar" o intervalo de valores, ou seja, dividir todo o intervalo de valores em uma série de intervalos e, em seguida, contar quantos valores se enquadram em cada intervalo. Os compartimentos geralmente são especificados como intervalos consecutivos e não sobrepostos de uma variável. Os compartimentos (intervalos) devem ser adjacentes e geralmente são (mas não precisam ser) de tamanho igual.

Além dos dados numéricos, os histogramas também podem ser usados para visualizar a distribuição de imagens, pois as imagens nada mais são do que uma combinação de elementos de imagem (pixels) que variam de $0$ a $255$. O eixo x do histograma indica o número de compartimentos, enquanto o eixo y representa a frequência de um compartimento específico. O número de compartimentos é um parâmetro que pode ser variado com base em como você deseja visualizar a distribuição dos dados.

Por exemplo: Digamos que você queira traçar um histograma de uma imagem RGB com valores de pixel que variam de $0$ a $255$. O máximo de compartimentos que essa imagem pode ter é $255$. Se você mantiver o eixo x (número de compartimentos) como $255$, o eixo y indicará a frequência de cada pixel nessa imagem.

Os histogramas são semelhantes em espírito aos gráficos bar. Vamos dar uma olhada em um exemplo pictórico de um histograma:

Um histograma é uma excelente ferramenta para visualizar e compreender a distribuição probabilística de dados numéricos ou dados de imagem que é intuitivamente compreendida por quase todo mundo. O Python tem muitas opções diferentes para criar e plotar histogramas. O Python tem poucas bibliotecas embutidas para criar gráficos, e uma delas é a matplotlib.

No tutorial de hoje, você usará principalmente o matplotlib para criar e visualizar histogramas em vários tipos de conjuntos de dados.

Portanto, sem mais delongas, vamos começar.

Plotagem de histograma usando NumPy e Matplotlib

import numpy as np

Para fins de reprodutibilidade, você usará a função seed do numPy, que fornecerá o mesmo resultado sempre que for executada.

Você traçará o histograma de gaussian (normal) distribution, que terá uma média de $0$ e um desvio padrão de $1$.

np.random.seed(100)
np_hist = np.random.normal(loc=0, scale=1, size=1000)
np_hist[:10]
array([-1.74976547,  0.3426804 ,  1.1530358 , -0.25243604,  0.98132079,
        0.51421884,  0.22117967, -1.07004333, -0.18949583,  0.25500144])

Vamos verificar a média e o desvio padrão da distribuição acima.

np_hist.mean(),np_hist.std()
(-0.016772157343909157, 1.0458427194167)

Em seguida, você usará a função histogram do numPy, que retornará hist e bin_edges.

hist,bin_edges = np.histogram(np_hist)
hist
array([  7,  37, 111, 207, 275, 213, 105,  31,  10,   4])
bin_edges
array([-3.20995538, -2.50316588, -1.79637637, -1.08958687, -0.38279736,
        0.32399215,  1.03078165,  1.73757116,  2.44436066,  3.15115017,
        3.85793967])

Em seguida, vamos plotar o histograma usando a função plt.bar do matplotlib, em que o eixo x e o eixo y serão bin_edges e hist, respectivamente.

import matplotlib.pyplot as plt
%matplotlib inline
plt.figure(figsize=[10,8])

plt.bar(bin_edges[:-1], hist, width = 0.5, color='#0504aa',alpha=0.7)
plt.xlim(min(bin_edges), max(bin_edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Normal Distribution Histogram',fontsize=15)
plt.show()

Vamos arredondar o bin_edges para um número inteiro.

bin_edges = np.round(bin_edges,0)
plt.figure(figsize=[10,8])

plt.bar(bin_edges[:-1], hist, width = 0.5, color='#0504aa',alpha=0.7)
plt.xlim(min(bin_edges), max(bin_edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Normal Distribution Histogram',fontsize=15)
plt.show()

Agora o gráfico está muito melhor, não é mesmo?

Para entender hist e bin_edges, vejamos um exemplo:

Você definirá uma matriz com valores arbitrários e definirá compartimentos com um intervalo de $5$.

hist, bin_edges = np.histogram([1, 1, 2, 2, 2, 2, 3],bins=range(5))
hist
array([0, 2, 4, 1])

Na saída acima, hist indica que há itens de $0$ no compartimento $0$, $2$ no compartimento $1$, $4$ no compartimento $3$, $1$ no compartimento $4$.

bin_edges
array([0, 1, 2, 3, 4])

Da mesma forma, a saída do site bin_edges acima significa que a posição $0$ está no intervalo $[0,1)$, a posição $1$ está no intervalo $[1,2)$, a posição $2$ está no intervalo $[2,3)$, a posição $3$ está no intervalo $[3,4)$.

Plotagem de histograma usando apenas o Matplotlib

Traçar um histograma usando matplotlib é muito fácil. Tudo o que você precisa fazer é usar a função plt.hist() do matplotlib e passar os dados juntamente com o número de compartimentos e alguns parâmetros opcionais.

Em plt.hist(), passar bins='auto' lhe dá o número "ideal" de bins. A ideia é selecionar uma largura de compartimento que gere a representação mais fiel de seus dados.

Isso é tudo. Então, vamos traçar o histograma do normal_distribution que você criou usando numpy.

plt.figure(figsize=[10,8])
n, bins, patches = plt.hist(x=np_hist, bins=8, color='#0504aa',alpha=0.7, rwidth=0.85)
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Normal Distribution Histogram',fontsize=15)
plt.show()

Plotagem conjunta de dois histogramas

plt.figure(figsize=[10,8])
x = 0.3*np.random.randn(1000)
y = 0.3*np.random.randn(1000)
n, bins, patches = plt.hist([x, y])

Traçando o histograma de dados da íris usando o Pandas

Você usará o site sklearn para carregar um conjunto de dados chamado iris. No sklearn, você tem uma biblioteca chamada datasets, na qual está o conjunto de dados do Iris, que pode ser carregado em tempo real. Então, vamos carregar rapidamente o conjunto de dados da íris.

from sklearn.datasets import load_iris
import pandas as pd
data = load_iris().data
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width']

Em seguida, você criará o dataframe do conjunto de dados iris.

dataset = pd.DataFrame(data,columns=names)
dataset.head()
  sepal-length largura da sépala petal-length largura da pétala
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
dataset.columns[0]
'sepal-length'

Por fim, você usará a função incorporada do pandas .hist() , que traçará histogramas para todos os recursos presentes no conjunto de dados.

Isso não é maravilhoso?

fig = plt.figure(figsize = (8,8))
ax = fig.gca()
dataset.hist(ax=ax)
plt.show()

O comprimento da pétala, a largura da pétala e o comprimento da sépala mostram uma distribuição unimodal, enquanto a largura da sépala reflete uma curva gaussiana. Todas essas análises são úteis, pois assim você pode pensar em usar um algoritmo que funcione bem com esse tipo de distribuição.

Plotar histograma com Matplotlib

plt.figure(figsize=[10,10])
f,a = plt.subplots(2,2)
a = a.ravel()
for idx,ax in enumerate(a):
    ax.hist(dataset.iloc[:,idx], bins='auto', color='#0504aa',alpha=0.7, rwidth=0.85)
    ax.set_title(dataset.columns[idx])
plt.tight_layout()
<Figure size 720x720 with 0 Axes>

Traçado de histograma de imagens binárias e RGB

No segmento final do tutorial, você visualizará duas imagens de domínios diferentes: imagens binárias (documentos) e naturais. As imagens binárias são aquelas em que os valores de pixel são, em sua maioria, $0$ ou $255$, enquanto uma imagem de canal colorido pode ter um valor de pixel que varia entre $0$ e $255$.

Analisar a distribuição de pixels traçando um histograma de valores de intensidade de uma imagem é a maneira correta de medir a ocorrência de cada pixel em uma determinada imagem. Para uma imagem em escala de cinza de 8 bits, há 256 valores de intensidade possíveis. Portanto, para estudar a diferença entre o documento e as imagens naturais no domínio da distribuição de pixels, você traçará dois histogramas para o documento e a imagem natural, respectivamente. Considerando que os documentos legíveis têm esparsidade, a distribuição de pixels nessas imagens de documentos deve ser mais distorcida.

Você usará o módulo opencv para carregar as duas imagens, convertê-las em escala de cinza passando um parâmetro $0$ durante a leitura e, por fim, redimensioná-las para o mesmo tamanho.

import cv2
lena_rgb = cv2.imread('lena.png')
lena_gray = cv2.cvtColor(lena_rgb,cv2.COLOR_BGR2GRAY)
lena_gray.shape
(512, 512)
binary = cv2.imread('binary.png')
binary.shape
(1394, 2190, 3)
binary = cv2.resize(binary,(512,512),cv2.INTER_CUBIC)
binary.shape
(512, 512, 3)
binary_gray = cv2.cvtColor(binary,cv2.COLOR_BGR2GRAY)
binary_gray.shape
(512, 512)

Vamos visualizar a imagem natural e a imagem do documento.

plt.figure(figsize=[10,10])

plt.subplot(121)
plt.imshow(lena_rgb[:,:,::-1])
plt.title("Natural Image")

plt.subplot(122)
plt.imshow(binary[:,:,::-1])
plt.title("Document Image")
plt.show()

Observação: Você usará bins igual a $255$, pois há um total de $255$ pixels em uma imagem e você deseja visualizar a frequência de cada valor de pixel da imagem variando de $0$ a $255$.

hist, edges = np.histogram(binary_gray,bins=range(255))
plt.figure(figsize=[10,8])

plt.bar(edges[:-1], hist, width = 0.8, color='#0504aa')
plt.xlim(min(edges), max(edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Document Image Histogram',fontsize=15)
plt.show()
hist, edges = np.histogram(lena_gray,bins=range(260))
plt.figure(figsize=[10,8])

plt.bar(edges[:-1], hist, width = 0.5, color='#0504aa')
plt.xlim(min(edges), max(edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Pixels',fontsize=15)
plt.ylabel('Frequency of Pixels',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Natural Image Histogram',fontsize=15)
plt.show()

Nas figuras acima, você pode observar que o natural image está espalhado por todas as 256 intensidades, tendo uma distribuição random, enquanto a imagem do documento mostra uma distribuição unimodal e é mais inclinada entre os valores de pixel $0$ e $255$.

Conclusão

Parabéns por terminar o tutorial.

Este tutorial foi um bom ponto de partida para saber como você pode criar um histograma usando o matplotlib com a ajuda do numpy e do pandas.

Você também aprendeu como aproveitar o poder do histograma para diferenciar dois domínios de imagem diferentes, ou seja, documento e imagem natural.

Se você quiser saber mais sobre técnicas de visualização de dados, considere fazer o curso DataCamp's Data Visualization with Matplotlib.

Fique à vontade para fazer qualquer pergunta relacionada a este tutorial na seção de comentários abaixo.

Temas

Saiba mais sobre Python

curso

Introduction to Data Visualization with Matplotlib

4 hr
181.1K
Learn how to create, customize, and share data visualizations using Matplotlib.
Ver DetalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado

tutorial

Introdução à plotagem com Matplotlib em Python

Este tutorial demonstra como usar o Matplotlib, uma poderosa biblioteca de visualização de dados em Python, para criar gráficos de linha, barra e dispersão com dados do mercado de ações.

Kevin Babitz

25 min

tutorial

Gráfico de linha de série temporal do Matplotlib

Este tutorial explora como criar e personalizar gráficos de linha de séries temporais no matplotlib.

tutorial

Gráficos de linhas no MatplotLib com Python

Este tutorial prático se aprofunda na criação e na personalização de gráficos de linhas com o Matplotlib, uma biblioteca avançada de visualização de dados em Python.
Arunn Thevapalan's photo

Arunn Thevapalan

11 min

tutorial

Tipos de gráficos de dados e como criá-los em Python

Explore vários tipos de gráficos de dados, desde os mais comuns até os avançados e não convencionais, o que eles mostram, quando usá-los, quando evitá-los e como criá-los e personalizá-los em Python.

tutorial

Tutorial do Python Seaborn Line Plot: Criar visualizações de dados

Descubra como usar o Seaborn, uma biblioteca popular de visualização de dados em Python, para criar e personalizar gráficos de linha em Python.

tutorial

Como fazer um histograma ggplot2 no R

Aprenda a criar um histograma ggplot2 no R. Crie histogramas no R com base na gramática dos gráficos.

Kevin Babitz

15 min

See MoreSee More