julio 30, 2020

~ 15 MIN

Matplotlib

< Blog RSS

Open In Colab

Matplotlib

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 o conda install matplotlib dependiendo de tu instalación de Python.

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

png

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

png

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

png

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

png

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

png

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

png

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

png

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

png

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

png

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

png

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)

png

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

png

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

png

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

png

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

png

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

png

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

png

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

png

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

png

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

png

# 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 de Python. 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

< Blog RSS