HOWTO · Pandas

Pandas-DataFrame-Zeilen nach Spaltenwerten filtern

Filtern Sie pandas-DataFrame-Zeilen mit booleschen Masken, loc, isin, between, Text- und Fehlwerttests oder query.

Auf dieser Seite

Beim Filtern entsteht für jede Zeile ein boolescher Wert; Zeilen mit True bleiben erhalten. Die allgemeine Form df.loc[Bedingung] ist eindeutig, und mit df.loc[Bedingung, Spalten] lassen sich zugleich Ausgabespalten wählen.

Beispiel-DataFrame erstellen

Die Beispieltabelle enthält Text, Zahlen, Datumswerte und einen fehlenden Produktnamen. Alle weiteren Beispiele verwenden orders. Der ursprüngliche Index bleibt erhalten; setzen Sie ihn nur mit .reset_index(drop=True) zurück, wenn ein neuer laufender Index benötigt wird.

import pandas as pd

orders = pd.DataFrame(
    {
        "order_id": [101, 102, 103, 104, 105, 106],
        "region": ["East", "West", "East", "North", "West", "East"],
        "product": ["Desk", "Chair", "Desk lamp", "Desk", None, "Chair"],
        "sales": [450, 275, 125, 700, 320, 410],
        "status": ["paid", "pending", "paid", "paid", "cancelled", "pending"],
        "ordered_at": pd.to_datetime(["2026-08-01", "2026-08-03", "2026-08-08", "2026-08-11", "2026-08-14", "2026-08-18"]),
    }
)

Zeilen nach einem Spaltenwert filtern

Ein Vergleich einer Series erzeugt die Maske. orders[orders["region"] == "East"] liefert dieselben Zeilen, .loc kann jedoch im zweiten Argument gezielt Spalten auswählen. != bildet die Gegenmenge; für Fehlwerte sind isna() und notna() präziser.

east_orders = orders.loc[orders["region"] == "East"]
print(east_orders[["order_id", "region", "sales"]].to_string(index=False))

Ausgabe:

 order_id region  sales
      101   East    450
      103   East    125
      106   East    410
large_orders = orders.loc[orders["sales"] >= 400, ["order_id", "sales"]]
print(large_orders.to_string(index=False))

Ausgabe:

 order_id  sales
      101    450
      104    700
      106    410

Mehrere Bedingungen kombinieren

Verknüpfen Sie elementweise Bedingungen mit &, | und ~, und setzen Sie jeden Vergleich in Klammern. Python-and und or erwarten einen einzigen Wahrheitswert und lösen bei einer Series den Fehler über einen mehrdeutigen Wahrheitswert aus.

mask = (orders["region"] == "East") & (orders["sales"] >= 400)
result = orders.loc[mask, ["order_id", "region", "sales"]]
print(result.to_string(index=False))

Ausgabe:

 order_id region  sales
      101   East    450
      106   East    410
mask = (orders["status"] == "paid") | (orders["sales"] > 600)
result = orders.loc[mask, ["order_id", "status", "sales"]]
# Raises ValueError: The truth value of a Series is ambiguous.
orders.loc[(orders["region"] == "East") and (orders["sales"] >= 400)]

Nach einer Werteliste filtern

Series.isin() ersetzt lange Ketten von Gleichheitsvergleichen. Übergeben Sie eine Liste oder eine andere listenartige Sammlung, keine einzelne Zeichenkette. ~ muss das vollständige Ergebnis von isin() negieren.

allowed = ["East", "West"]
result = orders.loc[orders["region"].isin(allowed), ["order_id", "region"]]
print(result.to_string(index=False))

Ausgabe:

 order_id region
      101   East
      102   West
      103   East
      105   West
      106   East
excluded = ["cancelled", "pending"]
paid_only = orders.loc[~orders["status"].isin(excluded)]

Bereiche und Datumswerte filtern

between(links, rechts) prüft standardmäßig einen einschließlich beider Grenzen definierten Bereich. Das funktioniert auch mit Datumswerten, nachdem die Spalte mit pd.to_datetime() konvertiert wurde. Bei Zeitzonen müssen Spalte und Grenzen kompatibel sein.

mid_value = orders.loc[orders["sales"].between(300, 500), ["order_id", "sales"]]
print(mid_value.to_string(index=False))

Ausgabe:

 order_id  sales
      101    450
      105    320
      106    410
date_mask = orders["ordered_at"].between("2026-08-03", "2026-08-14")
result = orders.loc[date_mask, ["order_id", "ordered_at"]]

Fehlende oder vorhandene Werte filtern

isna() findet None, NaN und NaT; notna() verlangt einen vorhandenen Wert. Eine leere Zeichenkette gilt nicht automatisch als fehlend und muss bei Bedarf getrennt normalisiert oder geprüft werden.

missing_product = orders.loc[orders["product"].isna(), ["order_id", "product"]]
present_product = orders.loc[orders["product"].notna()]
print(missing_product.to_string(index=False))

Ausgabe:

 order_id product
      105    None

Textwerte filtern

str.contains() erstellt eine vektorisierte Textmaske. regex=False behandelt Sonderzeichen wörtlich, case=False ignoriert Groß-/Kleinschreibung und na=False schließt fehlende Texte eindeutig aus.

has_desk = orders["product"].str.contains("desk", case=False, regex=False, na=False)
result = orders.loc[has_desk, ["order_id", "product"]]
print(result.to_string(index=False))

Ausgabe:

 order_id   product
      101      Desk
      103 Desk lamp
      104      Desk

DataFrame.query() für lesbare Ausdrücke verwenden

In query() kennzeichnet @ eine lokale Variable; Spaltennamen mit Leer- oder Sonderzeichen stehen in Backticks. Innerhalb der Abfrage sind and und or erlaubt. Bauen Sie aber niemals unkontrollierte Benutzereingaben in einen Abfrageausdruck ein, da dieser Code auswerten kann.

minimum_sales = 400
result = orders.query("region == 'East' and sales >= @minimum_sales")
print(result[["order_id", "region", "sales"]].to_string(index=False))

Ausgabe:

 order_id region  sales
      101   East    450
      106   East    410

Zwischen .loc, Klammern und query() wählen

Verwenden Sie .loc als gut lesbaren Standard, einfache Klammern für reine Zeilenauswahl und query() nur für kontrollierte, wirklich besser lesbare Ausdrücke. Vor einer Änderung des Ergebnisses schafft .copy() eine eindeutige unabhängige Arbeitskopie.

east_orders = orders.loc[orders["region"] == "East"].copy()
east_orders["sales_with_tax"] = east_orders["sales"] * 1.2

Ausrichtungs- und Datentypfehler vermeiden

Eine Maske ist eine beschriftete Series und wird bei .loc am Index ausgerichtet. Erstellen Sie sie daher aus demselben DataFrame. Konvertieren Sie Zahl- und Datumstext vor dem Vergleich; Groß-/Kleinschreibung und Leerzeichen bleiben bei exakten Textvergleichen bedeutsam.

Boolesche Masken wiederverwenden und prüfen

Benannte Teilmasken lassen sich zählen und einzeln prüfen. Ein leeres Ergebnis ist ein gültiger DataFrame; testen Sie bei Bedarf result.empty. DataFrame.filter() wählt Achsenbeschriftungen, nicht Zeilen anhand ihrer Zellwerte.

Filtern, ohne die Quelldaten zu verändern

Lesende Filter ändern orders nicht. Für Änderungen am Original weisen Sie mit orders.loc[mask, "status"] = "review" zu; für ein neues Arbeitsdataset verwenden Sie .copy(). So hängt das Verhalten nicht von verketteter Indizierung ab.

DataFrame.loc, Series.isin, Series.between, Series.str.contains, DataFrame.query