Skip to content
Themen
Matplotlib
Matplotlib fill_between: Conditional Fills, Bands, and isin() Fixes

Matplotlib fill_between: Bereich füllen, where und Konfidenzband

Veröffentlicht am

Aktualisiert am

Mit plt.fill_between / ax.fill_between Flächen zwischen Kurven füllen, mit where= bedingen, Konfidenzbänder zeichnen und ValueError bei Index-Filtern mit isin() beheben.

fill_between füllt die Fläche zwischen zwei y-Kurven (oder zwischen einer Kurve und einer Baseline). Es ist das Standardwerkzeug für Konfidenzbänder, „oberhalb/unterhalb“-Highlights und Region-Markierungen auf Liniendiagrammen.

Schnelle Syntax

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()
ZielMuster
Zwischen zwei Serien füllenax.fill_between(x, y1, y2, alpha=0.3)
Unter einer Linie füllenax.fill_between(x, 0, y, alpha=0.3)
Nur wo eine Bedingung giltwhere=(y1 > y2) (gleiche Länge wie x)
Index-/Kategorie-Filterwhere=df.index.isin([...]) — nicht Python-in
Glattere Kanten bei Bedingungeninterpolate=True

Was fill_between macht

Matplotlib baut ein Polygon von (x, y1) nach (x, y2) und füllt es. x, y1 und y2 müssen dieselbe Länge haben (oder y1/y2 dürfen Skalare sein).

Mit dieser einen Idee erledigt man die meisten „diese Region hervorheben“-Aufgaben, ohne eigene Patches zu bauen.

Basis: Fläche zwischen zwei Kurven

Dieses Beispiel füllt alles zwischen Sinus und Kosinus:

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

Nützliche Schalter:

  • alpha — Füllung transparent halten, damit Linien lesbar bleiben
  • color / facecolor — Füllfarbe
  • linewidth=0 — Polygonkante ausblenden, wenn sie mit Linienstilen kollidiert
  • label= — die Füllung in die Legende aufnehmen, wenn sie eine echte Kategorie darstellt

Bedingte Füllungen mit where=

Ein boolesches Array (gleiche Länge wie x) sorgt dafür, dass nur Teile des Bands gefärbt werden. Zwei Aufrufe, wenn zwei Farben gewünscht sind:

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

Warum interpolate=True zählt

Ohne Interpolation kann die Füllung an Stellen, an denen die Bedingung zwischen Sample-Punkten wechselt, mit blockigen vertikalen Kanten abbrechen. interpolate=True schätzt den Schnittpunkt, sodass das Highlight den Kurven sauberer folgt. Bei dichten, kontinuierlichen Serien bevorzugen; bei spärlichen, kategorialen x-Achsen ist es weniger wichtig.

Muster: Konfidenz- / Fehlerband

Ein sehr häufiges Praxis-Muster ist „Mittelwert ± Unsicherheit“:

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

Dieselbe Idee gilt für Quantile (p10/p90), Forecast-Bereiche oder Min/Max-Hüllen. Die Mittellinie nach der Füllung plotten oder mit höherem z-order, wenn die Füllung zu dominant wirkt.

Troubleshooting: nur bestimmte Kategorien / Monate füllen

Suchtraffic landet oft hier nach fehlgeschlagenen Versuchen wie:

# 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

Was schiefgeht

  • array in list ist nicht elementweise. NumPy-/pandas-Objekte werfen ValueError oder liefern einen einzelnen, mehrdeutigen Boolean.
  • Gebraucht wird ein boolescher Vektor, ausgerichtet an x, nicht ein True/False für das ganze Array.

Fix: isin() (oder np.isin)

Vollständiges, lauffähiges Beispiel mit kategorialen Monats-Labels:

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

Hinweise:

  • Bei DatetimeIndex boolesche Masken wie (df.index.month <= 3) oder .isin auf normalisierten Labels bevorzugen.
  • Liegen auf der Achse kategoriale Labels, sind Integer-Positionen an fill_between (wie oben) oft zuverlässiger als String-Kategorien.
  • where muss dieselbe Länge haben wie das übergebene x-Array.

Typische Fallen

FalleSymptomFix
Längen-MismatchValueError: ... not the same sizex, y1, y2, where angleichen
Python-in auf Index/ArrayValueError oder leere Füllungindex.isin([...]) / np.isin
alpha vergessenFüllung verdeckt Linienalpha=0.2–0.4
Außenlegende im PNG abgeschnittenLegende fehltSiehe Legende außerhalb des Plots + bbox_inches="tight"
Hässliche Bedingungskantenblockige Regioneninterpolate=True

Bei Multi-Serien-Charts Füllungen mit klaren Linienstilen aus mehreren Linienplots kombinieren. Wirkt die Figur nach Annotationen und Bändern eng, zuerst die Figure-Größe anpassen, bevor man an der Legende feilt.

fill_between vs fill_betweenx

  • fill_between(x, y1, y2) — vertikale Füllung zwischen zwei y-Werten über x (häufigster Fall).
  • fill_betweenx(y, x1, x2) — horizontale Füllung zwischen zwei x-Werten über y (nützlich für vertikale Profile, Dichte-Streifen, tornado-artige Bereiche).

Die where=-Idee gilt für beide.

FAQ

Fazit

ax.fill_between(x, y1, y2) ist die kleine API mit großem visuellen Effekt: Serien vergleichen, Unsicherheit zeigen, Regionen markieren. Bei bedingten Geschichten zu where= greifen, Labels mit isin/booleschen Masken statt Python-in filtern und alpha niedrig halten, damit die Daten im Vordergrund bleiben.

Verwandte Anleitungen