Direkt zum Inhalt

Pandas .apply(): Was es macht, wann es hilft und schnellere Alternativen

Lerne, was Python pandas .apply ist und wie du es für DataFrame nutzen kannst. Lerne noch heute, wie du mit der Funktion .apply() über DataFrames iterieren kannst!
Aktualisierte 7. Okt. 2025  · 5 Min. Lesezeit

Viele Leute greifen zu „ .apply() “, um „Schleifen zu vermeiden“, und denken, dass es schnell und einfach ist. .apply(axis=1) In der Praxis ist das zeilenweise Durchlaufen von Listen immer noch eine Schleife auf Python-Ebene. Bei großen Datenmengen kann es langsam sein und manchmal Formen liefern, die du nicht erwartet hast. Die Lösung ist einfach: Nutze vektorisierte Pandas-/NumPy-Operationen für alltägliche Aufgaben und behalte .apply() für Logik, die wirklich mehrere Spalten braucht.

Dieser Leitfaden zeigt, wie .apply() heute funktioniert, zeigt häufige Probleme auf und bietet Drop-in-Muster, die schneller und übersichtlicher sind.

Was sind DataFrame.apply() und Series.apply()?

DataFrame.apply(func, axis=0) ruft standardmäßig für jede Spalte die Funktion func auf . Mit axis=1 ” wird func ” für jede Zeile aufgerufen . Series.apply(func) ” ruft func ” für jedes Element auf (oder für die gesamte „ Series ”, je nach Signaturen in neueren Versionen).

  • Zeilenweise vs. spaltenweise: axis=1 bedeutet „pro Zeile”. axis=0 (Standard) heißt „pro Spalte”.
  • Regeln für die Rückgabe von Formen (Pandas ≥0.23): Wenn deine Funktion pro Zeile/Spalte einen Skalar zurückgibt, bekommst du einen „ Series “. Wenn es Series “ oder dict zurückgibt, erweitert Pandas diese Schlüssel zu „ DataFrame “. Wenn es eine Liste/ein Array zurückgibt, bekommst du eine Reihe von Listen, es sei denn, du setzt result_type='expand' “.
  • Strengere Fehler (pandas ≥2.0): Wenn Listenlängen jetzt nicht mehr passen, gibt's Fehlermeldungen, statt dass stillschweigend inkonsistente Ergebnisse produziert werden.

Empfohlene erste Wahl: Vektorisierte Operationen

Die meisten Aufgaben, bei denen Spalten kombiniert oder umgewandelt werden müssen, lassen sich mit vektorisierten Ausdrücken oder integrierten Methoden schneller und übersichtlicher erledigen. Das folgende Beispiel zeigt, wie man die Run-Differenz eines Baseballteams ohne .apply() berechnet.

import pandas as pd

team_stats = pd.DataFrame({
    "Team": ["ARI", "ATL", "BAL"],
    "League": ["NL", "NL", "AL"],
    "Year": [2012, 2012, 2012],
    "RunsScored": [734, 700, 712],
    "RunsAllowed": [688, 600, 705],
    "Wins": [81, 94, 93],
    "Games": [162, 162, 162],
    "Playoffs": [0, 1, 1],
})

# Vectorized: fast and idiomatic
team_stats["RunDiff"] = team_stats["RunsScored"] - team_stats["RunsAllowed"]
print(team_stats[["Team", "RunsScored", "RunsAllowed", "RunDiff"]])

Row-Wise .apply(), wenn du es wirklich brauchst

Verwende .apply(axis=1) , wenn deine Logik wirklich mehrere Spalten umfasst und nicht einfach vektorisiert werden kann (z. B. bedingte Regeln, die von mehreren Feldern abhängen).

einen abgeleiteten Wert aus mehreren Spalten berechnen

Dieses Muster berechnet einen Wert pro Zeile anhand mehrerer Eingaben. Der oben beschriebene vektorisierte Ansatz ist immer noch am besten, aber hier siehst du die richtige zeilenweise Verwendung und Optionen, die die Geschwindigkeit und Ausgabe beeinflussen.

def compute_run_diff(row):
    # Treat the row as read-only; return a scalar
    return row["RunsScored"] - row["RunsAllowed"]

# Row-wise apply (Python-level loop; can be slow on large data)
team_stats["RunDiff_apply"] = team_stats.apply(compute_run_diff, axis=1)

Wenn die Funktion numerisch ist und nur Roharrays braucht, überspringt man raw=True einige Pandas-Overhead-Kosten, indem ein NumPy-Array an die Funktion übergeben wird.

import numpy as np

def compute_run_diff_raw(values):
    # values is a NumPy array when raw=True
    # Order matches the column order we select
    rs, ra = values
    return rs - ra

team_stats["RunDiff_raw"] = team_stats[["RunsScored", "RunsAllowed"]].apply(
    compute_run_diff_raw, axis=1, raw=True
)

Überprüfe die Funktionseingabe einmal.

Wenn ich eine neue Zeilenfunktion anschließe, drucke ich einmal eine Zeile aus, um zu checken, was übergeben wird.

def debug_row(row):
    # Print the first row only
    if row.name == team_stats.index[0]:
        print("Example row:", row.to_dict())
    return 0

_ = team_stats.apply(debug_row, axis=1)

Fallstudien: Summen, Saison-Gesamtwerte und Textkennzeichnungen

Bei Jahresstatistiken von Rays solltest du integrierte Methoden und elementweise Tools bevorzugen, wenn möglich. .apply() , wo immer möglich.

rays_by_year = pd.DataFrame(
    {
        "Year": [2012, 2011, 2010, 2009, 2008],
        "RunsScored": [697, 707, 802, 803, 774],
        "RunsAllowed": [577, 614, 649, 754, 671],
        "Wins": [90, 91, 96, 84, 97],
        "Playoffs": [0, 1, 1, 0, 1],
    }
).set_index("Year")

Spaltensummen effizient berechnen

Verwende DataFrame.sum() anstelle von .apply(sum). Es ist schneller und klarer.

# Preferred
totals = rays_by_year.sum(axis=0)
print(totals)

# If you must use apply (not recommended here)
totals_apply = rays_by_year.apply(sum, axis=0)

die Gesamtpunktzahl einer Saison berechnen

Verwende vektorisierte Arithmetik über Spalten hinweg; nicht .apply() .

rays_by_year["TotalRuns"] = rays_by_year["RunsScored"] + rays_by_year["RunsAllowed"]
print(rays_by_year[["RunsScored", "RunsAllowed", "TotalRuns"]].head())

ein 0/1-Flag in Text umwandeln

Lieber Series.map() oder replace() für elementweise Transformationen in einer Spalte.

# Using map with a dict
rays_by_year["PlayoffsText"] = rays_by_year["Playoffs"].map({0: "No", 1: "Yes"})

# Equivalent with replace
rays_by_year["PlayoffsText2"] = rays_by_year["Playoffs"].replace({0: "No", 1: "Yes"})

Steuerung der Ausgangsform mit .apply()

Wenn deine Funktion mehr als einen Wert pro Zeile zurückgibt, musst du die Form explizit angeben. So vermeidest du Überraschungen und Probleme mit zukünftigen Versionen.

Gib eine Liste zurück und zerlege sie in Spalten.

Benutze result_type='expand' , um eine Liste/ein Array in mehrere Spalten aufzuteilen.

def wins_losses(row):
    # Derive wins and losses as two outputs
    wins = row["Wins"]
    losses = row["Games"] - row["Wins"] if "Games" in row else np.nan
    return [wins, losses]

# Example using team_stats, which has "Wins" and "Games"
expanded = team_stats.apply(wins_losses, axis=1, result_type="expand")
expanded.columns = ["WinsOut", "LossesOut"]
team_stats = pd.concat([team_stats, expanded], axis=1)

Gib eine Reihe oder ein Dict zurück, um Spalten automatisch zu benennen.

Rückgabe eines Series oder dict aus jeder Zeile zurück, um ein DataFrame mit passenden Spaltenbeschriftungen zu bekommen.

def summary_row(row):
    return pd.Series(
        {
            "IsWinningSeason": row["Wins"] >= 90,
            "RunRatio": (row["RunsScored"] / row["RunsAllowed"]),
        }
    )

summary = team_stats.apply(summary_row, axis=1)
team_stats = pd.concat([team_stats, summary], axis=1)

Wichtige Tipps zur Leistung

Zeilenweise .apply(axis=1) ist praktisch, aber bei großen Frames langsam, weil es deine Python-Funktion einmal pro Zeile aufruft. Diese Muster verhindern diesen Engpass.

  • Verwende lieber vektorisierte Pandas-/NumPy-Operationen und eingebaute Methoden wie sum, mean, clip, where, astypeund String-/Accessor-Methoden.
  • Für numerische Zeilen-/Spaltenoperationen, die Arrays akzeptieren, übergib raw=True , um ein NumPy-Array zu bekommen und den Overhead von pandas zu reduzieren.
  • Für elementweise Arbeit an einer einzelnen Spalte solltest du Series.map() oder vektorisierte Methoden anstelle von DataFrame.apply(axis=1).
  • Vermeide es, die angegebene Zeile/Spalte in deiner Funktion zu ändern; gib stattdessen einen neuen Wert zurück.

Wichtige Versionshinweise (pandas 2.x)

Die neuesten Pandas-Versionen haben das Verhalten rund um .apply() , damit die Ergebnisse besser vorhersehbar sind.

  • Listenartige Rückgaben: Ab Version 2.0 gibt's 'ne Fehlermeldung, wenn die Listen unterschiedlich lang sind. Verwende einheitliche Längen und setze result_type='expand' “, wenn du mehrere Spalten haben willst.
  • Ausbau der Produktion: Wenn du einen Series “ oder zurückgibst, wird das zu einem „DataFrame“ mit dict wird zu einem DataFrame mit diesen Schlüsseln als Spalten (stabil seit 0.23).
  • Series.apply() Änderungen: Das Argument „ convert_dtype “ wird nicht mehr unterstützt. Wenn du gemischte Typen brauchst, wandle sie zuerst in object um (zum Beispiel s.astype("object").apply(fn)). Mit den neuen Signaturen kann manin mehr Situationen festlegen, ob fn Skalare oder eine Serie bekommt (zum Beispiel by_row).

.apply() vs. .map() vs. .applymap() vs. .agg()

Such dir die API aus, die am besten zu deiner Transformation passt.

  • Series.map(func_or_dict): Elementweise Transformation einer Spalte. Am besten für Suchvorgänge oder einfache Funktionen geeignet.
  • DataFrame.apply(func, axis=1): Logik, die mehrere Spalten braucht.
  • DataFrame.apply(func, axis=0): Spaltenweise Logik (jeder Input ist eine Serie, die eine Spalte darstellt).
  • DataFrame.applymap(func): Elementweise über jede Zelle. Verwende es sparsam; vektorisierte Methoden sind schneller.
  • .agg()/.transform(): Aggregationen und gruppenweise Transformationen; diese sind in Groupby-Pipelines zu bevorzugen.

Häufige Fehler und schnelle Lösungen

Das sind die Probleme, die meistens zu falschen Ergebnissen oder Verzögerungen führen, mit Möglichkeiten, sie zu beheben.

  • Vergessen von axis=1 für die Zeilenlogik: Wenn deine Funktion plötzlich Spalten statt Zeilen bekommt, füge einfach “ axis=1 hinzu.
  • Unerwartete Liste: Wenn du eine Liste/ein Array aus jeder Zeile zurückgibst, setz result_type='expand' “, um sie in Spalten aufzuteilen.
  • Langsamer zeilenweiser Code: Ersetze sie durch vektorisierte Ausdrücke oder integrierte Funktionen; wenn das nicht geht, überleg dir, ob du raw=True ” nutzen kannst, um den Overhead zu reduzieren.
  • Die Eingabezeile ändern: Behandle Eingaben als schreibgeschützt und gib neue Werte zurück.
  • Typ-Drift: Wenn deine Funktion manchmal nicht ganzzahlige Werte zurückgibt, können ganzzahlige Spalten zu Float- oder Objekttypen hochkonvertiert werden. Gieß danach mit astype, falls nötig.

Fazit

.apply() ist ein flexibles Tool, aber es ist keine Abkürzung für die Leistung. Benutze vektorisierte Operationen für Arithmetik, Aggregation und elementweise Transformationen in einer einzelnen Spalte. Benutz „ DataFrame.apply(axis=1) “ nur, wenn du wirklich mehrere Spalten pro Zeile brauchst. Wenn du es benutzt, kontrolliere die Ausgabeform mit result_type “, schau dir „ raw=True “ für numerische Funktionen an und behalte „ dtypes “ im Auge. Diese Muster liefern vorhersehbare Ergebnisse auf modernen Pandas und lassen sich besser skalieren, wenn deine Datenmenge wächst.

Themen

Mehr über Python und Pandas erfahren

Kurs

Intermediate Python

4 Std.
1.3M
Erweitere deine Data-Science-Fähigkeiten und lerne, wie du mit Matplotlib Visualisierungen erstellst und DataFrames mit pandas bearbeitest.
Siehe DetailsRight Arrow
Kurs starten
Mehr anzeigenRight Arrow
Verwandt

Lernprogramm

Loop-Schleifen in Python-Tutorial

Lerne, wie du For-Schleifen in Python umsetzt, um eine Sequenz oder die Zeilen und Spalten eines Pandas-DataFrame zu durchlaufen.
Aditya Sharma's photo

Aditya Sharma

Lernprogramm

Python-Lambda-Funktionen: Ein Leitfaden für Anfänger

Lerne mehr über Python-Lambda-Funktionen, wozu sie gut sind und wann man sie benutzt. Enthält praktische Beispiele und bewährte Methoden für eine effektive Umsetzung.
Mark Pedigo's photo

Mark Pedigo

Lernprogramm

Python .append() und .extend() Methoden Tutorial

Lerne, wie du mit den Methoden .append() und .extend() Elemente zu einer Liste hinzufügst.
DataCamp Team's photo

DataCamp Team

Lernprogramm

Python-Arrays

Python-Arrays mit Code-Beispielen. Lerne noch heute, wie du mit Python NumPy Arrays erstellen und ausdrucken kannst!
DataCamp Team's photo

DataCamp Team

Lernprogramm

Wie man Listen in Python aufteilt: Einfache Beispiele und fortgeschrittene Methoden

Lerne, wie du Python-Listen mit Techniken wie Slicing, List Comprehensions und itertools aufteilen kannst. Finde heraus, wann du welche Methode für die beste Datenverarbeitung nutzen solltest.
Allan Ouko's photo

Allan Ouko

Lernprogramm

Fibonacci-Folge in Python: Lerne und entdecke Programmiertechniken

Finde raus, wie die Fibonacci-Folge funktioniert. Schau dir die mathematischen Eigenschaften und die Anwendungen in der echten Welt an.
Laiba Siddiqui's photo

Laiba Siddiqui

Mehr anzeigenMehr anzeigen