Transforme los aburridos gráficos de líneas predeterminados de Matplotlib en impresionantes visualizaciones personalizadas

Portada, imagen del autor

Todos los que han usado Matplotlib saben lo feos que se ven los gráficos predeterminados. En esta serie de publicaciones, compartiré algunos trucos para que tus visualizaciones se destaquen y reflejen tu estilo individual.

Comenzaremos con un gráfico de líneas simple, que se usa ampliamente. Lo más destacado será agregar un relleno degradado debajo del gráfico, una tarea que no es del todo sencilla.

Entonces, ¡profundicemos y repasemos todos los pasos clave de esta transformación!

Primero hagamos todas las importaciones necesarias.

import pandas as pd
import numpy as np
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib import rcParams
from matplotlib.path import Path
from matplotlib.patches import PathPatch

np.random.seed(38)

Ahora necesitamos generar datos de muestra para nuestra visualización. Crearemos algo similar a cómo se ven los precios de las acciones.

dates = pd.date_range(start='2024-02-01', periods=100, freq='D')
initial_rate = 75
drift = 0.003
volatility = 0.1
returns = np.random.normal(drift, volatility, len(dates))
rates = initial_rate * np.cumprod(1 + returns)

x, y = dates, rates

Veamos cómo se ve con la configuración predeterminada de Matplotlib.

fix, ax = plt.subplots(figsize=(8, 4))
ax.plot(dates, rates)
ax.xaxis.set_major_locator(mdates.DayLocator(interval=30))
plt.show()
Trama predeterminada, imagen por autor

Realmente no es fascinación, ¿verdad? Pero poco a poco lo haremos lucir mejor.

  • establecer el título
  • establecer parámetros generales del gráfico: tamaño y fuente
  • colocando las marcas Y a la derecha
  • cambiar el color, estilo y ancho de la línea principal
# General parameters
fig, ax = plt.subplots(figsize=(10, 6))
plt.title("Daily visitors", fontsize=18, color="black")
rcParams['font.family'] = 'DejaVu Sans'
rcParams['font.size'] = 14

# Axis Y to the right
ax.yaxis.tick_right()
ax.yaxis.set_label_position("right")

# Plotting main line
ax.plot(dates, rates, color='#268358', linewidth=2)

Parámetros generales aplicados, imagen del autor.

Muy bien, ahora se ve un poco más limpio.

Ahora nos gustaría agregar una cuadrícula minimalista al fondo, eliminar bordes para una apariencia más limpia y eliminar marcas del eje Y.

# Grid
ax.grid(color="gray", linestyle=(0, (10, 10)), linewidth=0.5, alpha=0.6)
ax.tick_params(axis="x", colors="black")
ax.tick_params(axis="y", left=False, labelleft=False)

# Borders
ax.spines["top"].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines["bottom"].set_color("black")
ax.spines['left'].set_color('white')
ax.spines['left'].set_linewidth(1)

# Remove ticks from axis Y
ax.tick_params(axis='y', length=0)

Cuadrícula agregada, imagen por autor

Ahora estamos agregando un pequeño detalle estético: el año cerca de la primera marca en el eje X. También hacemos que el color de fuente de las etiquetas de marca sea más pálido.

# Add year to the first date on the axis
def custom_date_formatter(t, pos, dates, x_interval):
date = dates[pos*x_interval]
if pos == 0:
return date.strftime('%d %b \'%y')
else:
return date.strftime('%d %b')
ax.xaxis.set_major_formatter(ticker.FuncFormatter((lambda x, pos: custom_date_formatter(x, pos, dates=dates, x_interval=x_interval))))

# Ticks label color
[t.set_color('#808079') for t in ax.yaxis.get_ticklabels()]
[t.set_color('#808079') for t in ax.xaxis.get_ticklabels()]

Año cercano a la primera cita, imagen del autor

Y nos acercamos al momento más complicado: cómo crear un degradado debajo de la curva. En realidad, no existe tal opción en Matplotlib, pero podemos simularla creando una imagen degradada y luego recortándola con el gráfico.

# Gradient
numeric_x = np.array([i for i in range(len(x))])
numeric_x_patch = np.append(numeric_x, max(numeric_x))
numeric_x_patch = np.append(numeric_x_patch[0], numeric_x_patch)
y_patch = np.append(y, 0)
y_patch = np.append(0, y_patch)

path = Path(np.array([numeric_x_patch, y_patch]).transpose())
patch = PathPatch(path, facecolor='none')
plt.gca().add_patch(patch)

ax.imshow(numeric_x.reshape(len(numeric_x), 1), interpolation="bicubic",
cmap=plt.cm.Greens,
origin='lower',
alpha=0.3,
extent=[min(numeric_x), max(numeric_x), min(y_patch), max(y_patch) * 1.2],
aspect="auto", clip_path=patch, clip_on=True)

Degradado añadido, imagen del autor.

Ahora se ve limpio y bonito. Sólo necesitamos agregar algunos detalles usando cualquier editor (prefiero Google Slides): título, esquinas redondeadas y algunos indicadores numéricos.

Visualización final, imagen del autor.

El código completo para reproducir la visualización se encuentra a continuación:

Por automata