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