julio 30, 2020
~ 15 MIN
Matplotlib
< Blog RSSMatplotlib
Seguimos nuestro viaje en la exploración de las librerías para análisis de datos
que el ecosistema de Python
nos ofrece. Hasta ahora hemos visto cómo empezar a trabajar con Python y las librerías de Numpy y Pandas. A esta lista agregamos la librería de visualización Matplotlib, la cual exploramos en detalle en este post y que nos va a permitir crear gráficos de calidad que podemos usar para comunicar nuestros descubrimientos, hipótesis y conclusiones.
Para empezar a trabajar con Matplotlib
, tenemos que importarlo.
import matplotlib
💡 Puedes instalar la librería con el comando
pip install matplotlib
oconda install matplotlib
dependiendo de tu instalación dePython
.
Al usar Matplotlib
en la línea de comandos o en un script de Python
, las gráficas nos aparecerán en una ventana separada. Sin embargo, al trabajar con notebooks, podemos visualizar nuestros gráficos directamente en el documento (lo cual es ideal a la hora de generar informes con código y visualizaciones en un solo documento). Ésto lo indicamos con el siguiente comando.
%matplotlib inline
Nuestro primer gráfico
En el siguiente ejemplo puedes ver como genera un sencillo gráfico. Para ello simplemente tenemos que llamar a la función plot
con una lista de valores para generar la imagen y show
para visualizarla.
import matplotlib.pyplot as plt
plt.plot([1, 2, 4, 9, 5, 3])
plt.show()
Como puedes ver, los valores de la lista se usan para el eje y
mientras que en el eje x
se utiliza el índice de cada valor en la lista. Podemos pasar dos listas a la función plot
para indicar los valores en ambos ejes.
plt.plot([-3, -2, 5, 0], [1, 6, 4, 3])
plt.show()
Puedes visualizar cualquier función matemática generando una lista con los valores de las variables independientes y calculando los valore de las variables dependientes con Numpy
de la siguiente manera
import numpy as np
x = np.linspace(-2, 2, 500)
y = x**2
plt.plot(x, y)
plt.show()
Customizando un gráfico
Ahora que conocemos la sintaxis básica para crear y visualizar un gráfico con Matplotlib
vamos a ver diferente funcionalidad que nos ofrece para tunear nuestro gráfico y hacerlo más bonito. Podemos empezar añadiendo un título y etiquetas a nuestros ejes. En ocasiones también es interesante añadir una cuadrícula en el fondo para mejorar la lectura de datos.
plt.plot(x, y)
plt.title("Mi gráfico")
plt.xlabel("x")
plt.ylabel("y = x**2")
plt.grid(True)
plt.show()
Podemos cambiar el estilo de la línea de manera sencilla pasando diferentes opciones en la función plot
, como un string que incluye el formato y color. Puedes encontrar una lista con los diferentes estilos en la documentación.
# línea negra punteada
plt.plot(x, y, '-.k')
plt.title("Mi gráfico")
plt.xlabel("x")
plt.ylabel("y = x**2")
plt.grid(True)
plt.show()
# diamantes rojos
x2 = np.linspace(-2, 2, 20)
y2 = x2**3
plt.plot(x2, y2, 'dr')
plt.title("Mi gráfico")
plt.xlabel("x")
plt.ylabel("y = x**3")
plt.grid(True)
plt.show()
Podemos añadir varias curvas en la misma gráfica simplemente llamando a la función plot
varias veces.
plt.plot(x, y, '-.k')
plt.plot(x2, y2, 'dr')
plt.title("Mi gráfico")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True)
plt.show()
Añadiendo una etiqueta a cada curva podemos generar una leyenda, la cual podemos situar en diferentes posiciones.
plt.plot(x, y, '-.k', label="y = x**2")
plt.plot(x2, y2, 'dr', label="y = x**3")
plt.title("Mi gráfico")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True)
plt.legend(loc='lower right')
plt.show()
Con la función axis
podemos delimitar la extensión de los ejes.
plt.plot(x, y, '-.k', label="y = x**2")
plt.plot(x2, y2, 'dr', label="y = x**3")
plt.title("Mi gráfico")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True)
plt.legend(loc='lower right')
plt.axis([-2,2,-4,4])
plt.show()
Por último vamos a ver cómo cambiar el tamaño del texto para que sea más legible. También podemos usar notación Latex
para introducir ecuaciones y símbolos en nuestros títulos, ejes y leyendas.
plt.plot(x, y, '-.k', label="$y = x^2$")
plt.plot(x2, y2, 'dr', label="$y = x^3$")
plt.title("Mi gráfico", fontsize=20)
plt.xlabel("x", fontsize=18)
plt.ylabel("y", fontsize=18)
plt.grid(True)
plt.legend(loc='lower right', fontsize=14)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.axis([-2,2,-4,4])
plt.show()
Ahora que tenemos nuestro gráfico listo, podemos guardarlo en un archivo simplemente sustituyendo la función show
por savefig
.
plt.plot(x, y, '-.k', label="$y = x^2$")
plt.plot(x2, y2, 'dr', label="$y = x^3$")
plt.title("Mi gráfico", fontsize=20)
plt.xlabel("x", fontsize=18)
plt.ylabel("y", fontsize=18)
plt.grid(True)
plt.legend(loc='lower right', fontsize=14)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.axis([-2,2,-4,4])
plt.savefig("mi_grafico.png", transparent=True)
Además de las opciones de customización que hemos visto existen muchas otras que podrás encontrar en la documentación, la cual incluye multitud de ejemplos útiles.
Múltiples gráficos
Una funcionalidad muy útil que Matplotlib
nos ofrece es la de generar varias gráficos en una misma figura. Vamos a ver cómo visualizar varias imágenes del dataset MNIST a la vez en una solo figura.
from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784', version=1)
X, y = mnist["data"], mnist["target"]
X.shape, y.shape
((70000, 784), (70000,))
X = X.reshape(-1, 28,28)
X.shape
(70000, 28, 28)
Empezamos definiendo una figura vacía con un tamaño determinado con la función figure
. Después, podemos añadir sub-figuras a la figure con la función subplot
indicando su posición en la figura global.
fig = plt.figure(figsize=(3,3))
ax = plt.subplot(1,1,1)
ax.imshow(X[0], cmap="gray")
plt.axis('off')
plt.show()
⚡ La función
imshow
nos permite visualizar imágenes. Puedes aprender más aquí.
En la función subplot
verás 3 números: número de filas, número de columnas y la posición de la sub-figura (empezando por 1). Podemos añadir más imágenes de la siguiente manera.
fig = plt.figure(figsize=(10,5))
ax = plt.subplot(1,3,1)
ax.imshow(X[0], cmap="gray")
ax.axis('off')
ax = plt.subplot(1,3,2)
ax.imshow(X[1], cmap="gray")
ax.axis('off')
ax = plt.subplot(1,3,3)
ax.imshow(X[2], cmap="gray")
ax.axis('off')
plt.show()
fig = plt.figure(figsize=(5,10))
ax = plt.subplot(3,1,1)
ax.imshow(X[0], cmap="gray")
ax.axis('off')
ax = plt.subplot(3,1,2)
ax.imshow(X[1], cmap="gray")
ax.axis('off')
ax = plt.subplot(3,1,3)
ax.imshow(X[2], cmap="gray")
ax.axis('off')
plt.show()
fig = plt.figure(figsize=(5,5))
ax = plt.subplot(2,2,1)
ax.imshow(X[0], cmap="gray")
ax.axis('off')
ax = plt.subplot(2,2,2)
ax.imshow(X[1], cmap="gray")
ax.axis('off')
ax = plt.subplot(2,2,3)
ax.imshow(X[2], cmap="gray")
ax.axis('off')
ax = plt.subplot(2,2,4)
ax.imshow(X[3], cmap="gray")
ax.axis('off')
plt.show()
También podemos combinar diferentes tipos de gráficos, con diferente extensión dentro de la gráfica global, para generar una figura como la siguiente.
fig = plt.figure(figsize=(5,5))
ax = plt.subplot(2,2,1)
ax.imshow(X[0], cmap="gray")
ax.axis('off')
ax = plt.subplot(2,2,2)
ax.imshow(X[1], cmap="gray")
ax.axis('off')
ax = plt.subplot(2,1,2)
ax.plot(x2, y2)
plt.show()
Otros tipos de gráficos
Además de la función plot
, Matplotlib
nos ofrece otras funciones para generar gráficos de otros tipos. Vamos a ver algunos ejemplos.
Scatter
La función scatter
nos permite visualizar un conjunto de puntos.
from numpy.random import rand
x, y = rand(2, 100)
plt.scatter(x, y)
plt.show()
Una opción muy interesante en este tipo de gráficos es visualizar cada punto con un color o tamaño diferente en función de otra variable, que puede representar una densidad, temperatura en una localización, etc.
for color in ['red', 'green', 'blue']:
n = 100
x, y = rand(2, n)
scale = 500.0 * rand(n) ** 5
plt.scatter(x, y, s=scale, c=color, alpha=0.3, edgecolors='blue')
plt.grid(True)
plt.show()
Histogramas
Otro tipo de gráfico muy útil es el histograma de barras. Usamos la función hist
a la cual podemos indicarle el número de barras con la opción bins
.
data = [1, 1.1, 1.8, 2, 2.1, 3.2, 3, 3, 3, 3]
plt.hist(data, bins = 10, rwidth=0.8)
plt.show()
Animaciones
Vamos a terminar viendo cómo generar animaciones, una funcionalidad muy útil que nos permite generar vídeos o gifs que pueden quedar muy bien en presentaciones. En el siguiente ejemplo veremos como generar una animación similar a la usada en el primer post del Perceptrón en el que vimos la evolución de nuestro modelo a medida que lo entrenamos.
# datos para entrenar el perceptrón
np.random.seed(42)
x = np.random.rand(20)
y = 2*x + (np.random.rand(20)-0.5)*0.5
plt.plot(x, y, "b.")
plt.xlabel("$x_1$", fontsize=14)
plt.ylabel("$y$", rotation=0, fontsize=14)
plt.grid(True)
plt.show()
# funciones necesarias para entrenar el perceptrón
def gradient(w, x, y):
# calculamos la derivada de la función de pérdida
# con respecto a los parámteros `w`
dldw = x*w - y
dydw = x
dldw = dldw*dydw
return np.mean(2*dldw)
def cost(y, y_hat):
# calculamos la función de pérdida
return ((y_hat - y)**2).mean()
def solve(epochs = 29, w = 1.2, lr = 0.2):
# iteramos un número determinado de `epochs`
# por cada epoch, calculamos gradientes y
# actualizamos los pesos
weights = [(w, gradient(w, x, y), cost(x*w, y))]
for i in range(1,epochs+1):
dw = gradient(w, x, y)
w = w - lr*dw
weights.append((w, dw, cost(x*w, y)))
return weights
Para generar la animación usamos el objeto animation
y su función FuncAnimation
, a la cual le podemos pasar el número de frames totales en la animación así como la figura sobre la que queremos aplicar la animación y la función con la lógica para actualizarla en cada frame. También configuramos Matplotlib
para visualizar la animación como un vídeo en HTML
.
# animación
from matplotlib import animation, rc
rc('animation', html='html5')
def update(i):
xs = np.linspace(0, 1, num=100)
(w, dw, cost) = weights[i]
ax.clear()
ax.plot(x, y, "b.")
ax.plot(xs, w*xs, "-k")
ax.set_xlabel("$x_1$", fontsize=14)
ax.set_ylabel("$y$", rotation=0, fontsize=14)
ax.set_title(f"Iteración: {i}")
ax.grid(True)
ax.axis([0,1,0,2])
return ax
weights = solve()
fig = plt.figure(figsize=(10,6))
ax = plt.subplot(1,1,1)
anim = animation.FuncAnimation(fig, update, frames=len(weights), interval=100)
plt.close()
anim
Una vez generada la animación puedes descargarla desde el widget creado.
⚡ Para poder generar animaciones tendrás que instalar la librería
ffmpeg
, la cual no forma parte dePython
. Puedes ver las instrucciones para instalarlo aquí.
Resumen
En este post hemos presentado varios ejemplos de gráficos que podemos generar con Matplotlib
, aún así existen muchas otras opciones que no hemos visto. Una buena idea es ojear los diferentes ejemplos disponibles en la galería de Matplotlib
y utilizar el código para generar el gráfico que más se parezca al que quieres generar, y trabajar a partir de ahí.
Referencias
- https://matplotlib.org/gallery.html
- Python for Data Analysis by Wes McKinney (O’Reilly). Copyright 2017 Wes McKinsey, 978-1-491-95766-0.
- https://github.com/ageron/handson-ml2/blob/master/tools_matplotlib.ipynb