Skip to content
Temas
Matplotlib
Matplotlib fill_between: relleno condicional, bandas y arreglos con isin()

Matplotlib fill_between: relleno condicional, bandas y arreglos con isin()

Publicado el

Actualizado el

Usa plt.fill_between / ax.fill_between para rellenar entre curvas, resaltar condiciones con where=, crear bandas de confianza y corregir ValueError al filtrar etiquetas del índice con isin().

fill_between rellena el área entre dos curvas en y (o entre una curva y una línea base). Es la herramienta habitual para bandas de confianza, resaltados “por encima/por debajo” y regiones destacadas en gráficos de líneas.

Sintaxis rápida

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 200)
y1 = np.sin(x)
y2 = np.cos(x)
 
fig, ax = plt.subplots()
ax.plot(x, y1, label="sin")
ax.plot(x, y2, label="cos")
ax.fill_between(x, y1, y2, color="0.7", alpha=0.4)
ax.legend()
plt.show()
ObjetivoPatrón
Rellenar entre dos seriesax.fill_between(x, y1, y2, alpha=0.3)
Rellenar bajo una líneaax.fill_between(x, 0, y, alpha=0.3)
Solo donde se cumple una condiciónwhere=(y1 > y2) (misma longitud que x)
Filtro por índice / categoríawhere=df.index.isin([...]) — no el in de Python
Bordes más suaves en condicionesinterpolate=True

Qué hace fill_between

Matplotlib dibuja un polígono de (x, y1) a (x, y2) y lo rellena. x, y1 y y2 deben tener la misma longitud (o y1/y2 pueden ser escalares).

Con esa sola idea cubres la mayoría de tareas de “resalta esta región” sin inventar patches a mano.

Relleno básico entre dos curvas

Este ejemplo rellena todo el área entre seno y coseno:

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 300)
y1 = np.sin(x)
y2 = np.cos(x)
 
fig, ax = plt.subplots(figsize=(7.2, 4.2))
ax.plot(x, y1, label="sin(x)", color="#2563eb", lw=2)
ax.plot(x, y2, label="cos(x)", color="#dc2626", lw=2)
ax.fill_between(x, y1, y2, color="#94a3b8", alpha=0.45)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.legend(loc="upper right")
plt.show()

Basic fill_between between sine and cosine

Controles útiles:

  • alpha — deja el relleno semitransparente para que las líneas se lean
  • color / facecolor — color del relleno
  • linewidth=0 — oculta el borde del polígono si pelea con el estilo de las líneas
  • label= — incluye el relleno en la leyenda cuando representa una categoría real

Rellenos condicionales con where=

Pasa un array booleano (misma longitud que x) para pintar solo parte de la banda. Usa dos llamadas si quieres dos colores:

fig, ax = plt.subplots(figsize=(7.2, 4.2))
ax.plot(x, y1, label="sin(x)", color="#2563eb", lw=2)
ax.plot(x, y2, label="cos(x)", color="#dc2626", lw=2)
 
ax.fill_between(
    x, y1, y2,
    where=(y1 > y2),
    interpolate=True,
    color="#22c55e",
    alpha=0.35,
    label="sin > cos",
)
ax.fill_between(
    x, y1, y2,
    where=(y1 <= y2),
    interpolate=True,
    color="#f97316",
    alpha=0.30,
    label="sin ≤ cos",
)
 
ax.legend(loc="upper right", ncol=2)
plt.show()

Conditional fill_between using where

Por qué importa interpolate=True

Sin interpolación, el relleno puede cortar con bordes verticales “a bloques” donde la condición cambia entre puntos de muestreo. interpolate=True estima el cruce para que el resaltado siga las curvas con más limpieza. Prefiérelo en series continuas densas; importa menos en ejes x categóricos dispersos.

Patrón de banda de confianza / error

Un uso muy habitual en la práctica es “media ± incertidumbre”:

t = np.linspace(0, 12, 200)
mean = np.sin(t / 1.5) + 0.15 * t
std = 0.35 + 0.08 * np.abs(np.cos(t))
 
fig, ax = plt.subplots(figsize=(7.2, 4.2))
ax.plot(t, mean, color="#0f766e", lw=2.2, label="estimate")
ax.fill_between(t, mean - std, mean + std, color="#14b8a6", alpha=0.28, label="±1σ band")
ax.set_xlabel("time")
ax.set_ylabel("value")
ax.legend(loc="upper left")
plt.show()

Confidence-style band with fill_between

La misma idea sirve para cuantiles (p10/p90), rangos de pronóstico o envolventes min/max. Dibuja la línea central después o con un z-order más alto si el relleno se impone demasiado.

Diagnóstico: rellenar solo algunas categorías / meses

Gran parte del tráfico de búsqueda llega a esta página tras un intento fallido como:

# Broken ideas
where = plotMonths.index in ["January", "February", "March"]   # ValueError / nonsense
where = [m in ["January", "February", "March"] for m in plotMonths.index]  # may work, but isin is cleaner

Qué sale mal

  • array in list no es elemento a elemento. Los objetos de NumPy/pandas lanzan ValueError o devuelven un único booleano ambiguo.
  • Necesitas un vector booleano alineado con x, no un True/False para todo el array.

Arreglo: isin() (o np.isin)

Ejemplo completo y ejecutable con etiquetas de meses categóricos:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
 
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug"]
df = pd.DataFrame(
    {
        "A": [12, 14, 13, 15, 18, 17, 16, 19],
        "B": [10, 11, 12, 14, 13, 15, 14, 16],
    },
    index=months,
)
 
fig, ax = plt.subplots(figsize=(7.2, 4.2))
ax.plot(df.index, df["A"], marker="o", label="series A")
ax.plot(df.index, df["B"], marker="o", label="series B")
 
ax.fill_between(
    np.arange(len(df)),
    df["A"],
    df["B"],
    where=df.index.isin(["Jan", "Feb", "Mar"]),
    color="#38bdf8",
    alpha=0.35,
    label="Q1 highlight",
)
 
ax.set_xticks(range(len(df)), df.index)
ax.legend(loc="upper left")
plt.show()

Selected months highlighted with isin

Notas:

  • Con un DatetimeIndex, prefiere máscaras booleanas como (df.index.month <= 3) o .isin sobre etiquetas normalizadas.
  • Cuando el eje x son etiquetas categóricas, pasar posiciones enteras a fill_between (como arriba) suele ser más fiable que categorías string.
  • Mantén la longitud de where igual al array x que pasas.

Trampas frecuentes

TrampaSíntomaArreglo
Longitudes distintasValueError: ... not the same sizeAlinea x, y1, y2, where
Usar el in de Python sobre Index/arrayValueError o relleno vacíoindex.isin([...]) / np.isin
Olvidar alphaEl relleno tapa las líneasalpha=0.2–0.4
Leyenda fuera recortada en PNGLeyenda cortadaVer leyenda fuera del gráfico + bbox_inches="tight"
Bordes feos en condicionesRegiones a bloquesinterpolate=True

En gráficos multi-serie, combina rellenos con estilos de línea claros de múltiples gráficos de líneas. Si la figura se siente apretada tras anotaciones y bandas, ajusta el tamaño de figura antes de pelear con la leyenda.

fill_between vs fill_betweenx

  • fill_between(x, y1, y2) — relleno vertical entre dos valores y a lo largo de x (el más habitual).
  • fill_betweenx(y, x1, x2) — relleno horizontal entre dos valores x a lo largo de y (útil para perfiles verticales, franjas de densidad, rangos estilo tornado).

La misma idea de where= aplica a ambos.

FAQ

Conclusión

ax.fill_between(x, y1, y2) es una API pequeña con mucho impacto visual: comparar series, mostrar incertidumbre y marcar regiones. Usa where= cuando la historia sea condicional, isin/máscaras booleanas en lugar del in de Python para etiquetas, y mantén alpha bajo para que los datos sigan mandando.

Related Guides