Saltar al contenido principal
InicioAcerca de PythonAprender Python

Histogramas en Matplotlib

Aprende sobre histogramas y cómo puedes utilizarlos para obtener información de los datos con la ayuda de matplotlib.
abr 2024  · 8 min leer

Introducción

Según la Wikipedia, un histograma es una representación gráfica precisa de la distribución de datos numéricos. Es una estimación de la distribución de probabilidad de una variable continua (variable cuantitativa) y fue presentada por primera vez por Karl Pearson. Es un tipo de gráfico de barras. Para construir un histograma, el primer paso es dividir en "bin” el intervalo de valores, es decir, dividir todo el intervalo de valores en una serie de intervalos, y luego contar cuántos valores quedan incluidos en cada intervalo. Los bins suelen especificarse como intervalos consecutivos y no solapados de una variable. Los bins (intervalos) deben ser adyacentes y suelen ser (pero no es obligatorio que lo sean) de igual tamaño.

Aparte de los datos numéricos, los histogramas también pueden utilizarse para visualizar la distribución de las imágenes, ya que éstas no son más que una combinación de elementos de imagen (píxeles) que oscilan entre $0$ y $255$. El eje x del histograma denota el número de intervalos, mientras que el eje y representa la frecuencia de un intervalo concreto. El número de intervalos es un parámetro que se puede modificar en función de cómo quieras visualizar la distribución de tus datos.

Por ejemplo: Supongamos que quieres trazar un histograma de una imagen RGB con valores de píxel comprendidos entre $0$ y $255$. El máximo de intervalos que puede tener esta imagen es $255$. Si mantienes x_axis (número de intervalos) como $255$, entonces el y_axis denotará la frecuencia de cada píxel en esa imagen.

Los histogramas son similares en esencia a los gráficos de bar, veamos un ejemplo pictórico de histograma:

Un histograma es una herramienta excelente para visualizar y comprender la distribución probabilística de datos numéricos o datos de imagen que casi todo el mundo entiende intuitivamente. Python tiene muchas opciones diferentes para construir y trazar histogramas. Python tiene algunas bibliotecas incorporadas para crear gráficos, y una de ellas es matplotlib.

En el tutorial de hoy, utilizarás sobre todo matplotlib para crear y visualizar histogramas en varios tipos de conjuntos de datos.

Así que, sin más preámbulos, empecemos.

Trazar un histograma con NumPy y Matplotlib

import numpy as np

Para que sea reproducible, utilizarás la función seed de numPy, que dará el mismo resultado cada vez que se ejecute.

Trazarás el histograma de gaussian (normal) distribution, que tendrá una media de $0$ y una desviación típica 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])

Comprobemos la media y la desviación típica de la distribución anterior.

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

A continuación, utilizarás la función histogram de numPy, que devolverá hist y 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])

A continuación, vamos a trazar el histograma utilizando la función plt.bar de matplotlib, donde el eje x y el eje y serán bin_edges y 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()

Redondeemos el bin_edges a un número entero.

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()

Ahora el gráfico tiene mucho mejor aspecto, ¿verdad?

Para entender hist y bin_edges, veamos un ejemplo:

Definirás una matriz con valores arbitrarios y definirás intervalos con un rango de $5$.

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

En la salida anterior, hist indica que hay $0$ artículos en el intervalo $0$, $2$ en el intervalo $1$, $4$ en el intervalo $3$ y $1$ en el intervalo $4$.

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

Del mismo modo, la salida bin_edges anterior significa que el intervalo $0$ está en el intervalo $[0,1)$, el intervalo $1$ está en el intervalo $[1,2)$, el intervalo $2$ está en el intervalo $[2,3)$, y el intervalo $3$ está en el intervalo $[3,4)$.

Trazar un histograma utilizando solamente Matplotlib

Trazar un histograma utilizando matplotlib es pan comido. Todo lo que tienes que hacer es utilizar la función plt.hist() de matplotlib y pasar los datos junto con el número de intervalos y algunos parámetros opcionales.

En plt.hist(), si pasas bins='auto' obtendrás el número "ideal" de intervalos. La idea es seleccionar una amplitud de intervalo que genere la representación más fiel de tus datos.

Eso es todo. Así pues, vamos a trazar el histograma de normal_distribution que has construido utilizando 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()

Trazar dos histogramas juntos

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])

Trazar un histograma de datos Iris con Pandas

Utilizarás sklearn para cargar un conjunto de datos llamado iris. En sklearn, tienes una biblioteca llamada datasets en la que tienes el conjunto de datos Iris que se puede cargar sobre la marcha. Así pues, vamos a cargar rápidamente el conjunto de datos Iris.

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

A continuación, crearás el marco de datos del conjunto de datos iris.

dataset = pd.DataFrame(data,columns=names)
dataset.head()
  sepal-length sepal-width petal-length petal-width
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 último, utilizarás la función incorporada de pandas .hist() , que trazará histogramas para todas las características presentes en el conjunto de datos.

¿No es maravilloso?

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

La longitud de los pétalos, la anchura de los pétalos y la longitud de los sépalos muestran una distribución unimodal, mientras que la anchura de los sépalos refleja una curva gaussiana. Todos estos análisis son útiles porque entonces puedes pensar en utilizar un algoritmo que funcione bien con este tipo de distribución.

Trazar un histograma con 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>

Trazado del histograma de imágenes binarias y RGB

En el segmento final del tutorial, visualizarás dos imágenes de dominio diferentes: imágenes binarias (de documentos) e imágenes naturales. Las imágenes binarias son aquellas cuyos valores de píxel son en su mayoría de $0$ o $255$, mientras que una imagen de canal de color puede tener un valor de píxel que oscile entre $0$ y $255$.

Analizar la distribución de píxeles trazando un histograma de valores de intensidad de una imagen es la forma correcta de medir la aparición de cada píxel en una imagen determinada. Para una imagen en escala de grises de 8 bits, hay 256 valores de intensidad posibles. Por tanto, para estudiar la diferencia entre el documento y las imágenes naturales en el dominio de la distribución de píxeles, trazarás dos histogramas, uno para el documento y otro para la imagen natural, respectivamente. Teniendo en cuenta que los documentos legibles tienen escasez, la distribución de píxeles en estas imágenes de documentos debe ser mayoritariamente sesgada.

Utilizarás el módulo opencv para cargar las dos imágenes, convertirlas a escala de grises pasándoles un parámetro $0$ al leerlas, y finalmente redimensionarlas al mismo tamaño.

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)

Visualicemos tanto la imagen natural como la del 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()

Nota: Utilizarás bins igual a $255$, ya que hay un total de $255$ píxeles en una imagen y quieres visualizar la frecuencia de cada valor de píxel de la imagen que va 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()

En las figuras anteriores, puedes observar que la natural image está repartida entre las 256 intensidades y tiene una distribución random, mientras que la imagen del documento muestra una distribución unimodal y está sesgada principalmente entre los valores de píxel de $0$ a $255$.

Conclusión

Enhorabuena por terminar el tutorial.

Este tutorial ha sido un buen punto de partida para saber cómo puedes crear un histograma utilizando matplotlib con la ayuda de numpy y pandas.

También has aprendido a aprovechar el poder de los histogramas para diferenciar entre dos dominios de imagen distintos, a saber, el documento y la imagen natural.

Si quieres aprender más sobre técnicas de visualización de datos, considera la posibilidad de realizar el curso Visualización de datos con Matplotlib de Datacamp.

No dudes en hacer cualquier pregunta relacionada con este tutorial en la sección de comentarios más abajo.

Temas

Más información sobre Python

Course

Introduction to Data Visualization with Matplotlib

4 hr
172.4K
Learn how to create, customize, and share data visualizations using Matplotlib.
See DetailsRight Arrow
Start Course
Ver másRight Arrow
Relacionado

tutorial

Introducción al trazado con Matplotlib en Python

Este tutorial muestra cómo utilizar Matplotlib, una potente biblioteca de visualización de datos en Python, para crear gráficos de líneas, barras y dispersión con datos bursátiles.

Kevin Babitz

25 min

tutorial

Gráfico lineal de series temporales Matplotlib

Este tutorial explora cómo crear y personalizar gráficos de líneas de series temporales en matplotlib.
Elena Kosourova's photo

Elena Kosourova

8 min

tutorial

Gráficos lineales en MatplotLib con Python

Este tutorial práctico profundiza en la creación y personalización de gráficos lineales con Matplotlib, una potente biblioteca de visualización de datos en Python.
Arunn Thevapalan's photo

Arunn Thevapalan

11 min

tutorial

Tipos de gráficos de datos y cómo crearlos en Python

Explore varios tipos de gráficos de datos, desde los más comunes hasta los más avanzados y poco convencionales, qué muestran, cuándo utilizarlos, cuándo evitarlos y cómo crearlos y personalizarlos en Python.
Elena Kosourova's photo

Elena Kosourova

21 min

tutorial

Tutorial de Python Seaborn Line Plot: Crear visualizaciones de datos

Descubra cómo utilizar Seaborn, una popular biblioteca de visualización de datos de Python, para crear y personalizar gráficos de líneas en Python.
Elena Kosourova's photo

Elena Kosourova

12 min

tutorial

Python Seaborn Tutorial Para Principiantes: Empezar a visualizar datos

Este tutorial de Seaborn le introduce en los fundamentos de la visualización de datos estadísticos
Moez Ali's photo

Moez Ali

20 min

See MoreSee More