HOWTO · Pandas
Vektorisieren Sie eine Funktion in Pandas
Dieses Tutorial zeigt, wie wir eine Funktion in Pandas vektorisieren können.
Auf dieser Seite
Um eine Funktion in pandas zu vektorisieren, formulieren Sie ihre Berechnung zunächst mit Operationen um, die eine gesamte Series oder ein NumPy-Array verarbeiten. So vermeiden Sie in der Regel, für jeden einzelnen Wert eine Python-Funktion aufzurufen. Lässt sich die Logik nicht mit passenden Array-Operationen ausdrücken, verwenden Sie Series.map für eine übersichtliche elementweise Transformation. Series.apply ist eine weitere Möglichkeit für Operationen pro Wert, schaltet aber keine Vektorisierung ein.
Eine Funktion in Pandas vektorisieren
Dieses Beispiel vergleicht eine eigene Funktion mit einem Array-Ausdruck, um eine Gehaltsanpassung vorzunehmen. Die Daten werden direkt im Beispiel erstellt, der Code benötigt also keine externe Datei. Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
import pandas as pd
pay = pd.Series([1000.0, 2000.0, 3000.0], name="pay")
def add_tax(value):
return value * 1.05 + 1
mapped = pay.map(add_tax)
vectorized = pay * 1.05 + 1
applied = pay.apply(add_tax)
reference = pd.Series([1051.0, 2101.0, 3151.0], name="pay")
print(vectorized.tolist())
print(mapped.equals(vectorized))
print(applied.equals(vectorized))
print(vectorized.equals(reference))
Bei erfolgreicher Ausführung wird Folgendes ausgegeben:
[1051.0, 2101.0, 3151.0]
True
True
True
Was Vektorisierung für eine Pandas-Series bedeutet
Eine pandas-Series speichert beschriftete Werte. Ein Ausdruck wie pay * 1.05 + 1 führt die Rechenoperation auf der Series aus und behält dabei ihren Index bei. Das ist arrayorientierter Code: pandas und die zugrunde liegenden Bibliotheken verarbeiten die Daten, statt dass Ihr Code add_tax ausdrücklich für jeden einzelnen Wert aufruft.
Vektorisierung beschreibt, wie eine Operation formuliert und verarbeitet wird; sie garantiert keine bestimmte Implementierung. Eine pandas-Operation kann intern weiterhin Schleifen verwenden. Gehen Sie auch nicht davon aus, dass sie SIMD-Anweisungen nutzt. Entscheidend ist in der Praxis, dass eine passende Series- oder NumPy-Operation Python-Funktionsaufrufe auf Ebene einzelner Elemente vermeiden kann. Ob das schneller ist, hängt von der Operation, der Datenmenge, den Datentypen und der Umgebung ab.
Eine Funktion mit Series.map elementweise anwenden
Verwenden Sie Series.map, wenn eine eigene Funktion für einzelne Werte die Transformation am klarsten beschreibt. Im Beispiel ruft pay.map(add_tax) add_tax für jeden Wert auf und gibt eine Series mit dem Index der Eingabe zurück. Die Funktion sollte einen einzelnen Wert entgegennehmen und den transformierten Wert zurückgeben. Dieses Muster eignet sich für eigene Regeln oder Zuordnungen, für die es keinen passenden direkten Array-Ausdruck gibt.
Für eine feste Zuordnung können Sie Series.map auch ein Dictionary übergeben. Werte ohne passenden Schlüssel werden dabei zu fehlenden Werten. Prüfen Sie dieses Verhalten, wenn die Zuordnung nicht alle möglichen Eingaben abdeckt. Bei einfachen Rechenoperationen ist der Series-Ausdruck vorzuziehen: Er beschreibt die Operation direkt und vermeidet, Python-Code für einzelne Werte in einen elementweisen Aufruf einzubetten.
Die Funktion in Array-Operationen umschreiben
Die Funktion add_tax berechnet value * 1.05 + 1. Da Multiplikation und Addition für eine Series unterstützt werden, lässt sich dieselbe Regel als pay * 1.05 + 1 ausdrücken. Genau darin besteht die sinnvolle Form der Vektorisierung: Formulieren Sie die Logik mit Operationen um, die auf dem gesamten Array arbeiten, statt die ursprüngliche Python-Funktion wiederholt anzuwenden.
Wählen Sie für eine DataFrame-Spalte die Spalte als Series aus und wenden Sie denselben Ausdruck an, zum Beispiel df["TotalPay"] * 1.05 + 1. Weisen Sie das Ergebnis einer neuen Spalte zu, wenn Sie es zusammen mit den Quelldaten behalten möchten. Bei Zuweisungen und bei Rechenoperationen zwischen Series richtet pandas die Werte anhand des Index aus. Prüfen Sie daher, ob die Indizes übereinstimmen, wenn Sie separat erstellte Daten kombinieren.
Zwischen Vektorisierung, map und apply wählen
Verwenden Sie einen Series- oder NumPy-Ausdruck, wenn die Operation für den Array-Datentyp verfügbar ist. Series.map eignet sich für eine Transformation oder Zuordnung einzelner Werte. Verwenden Sie Series.apply, wenn eine Funktion für einzelne Werte benötigt wird und map die Aufgabe weniger klar ausdrückt. Sowohl map als auch der übliche Ausführungspfad von Series.apply rufen Python-Logik für einzelne Werte auf; keine der beiden Methoden macht aus einer skalaren Funktion automatisch nativen vektorisierten Code.
Berechnen Sie einen Mittelwert nicht, indem Sie np.mean mit einer Schleife oder Series.apply für jeden einzelnen Wert aufrufen. Verwenden Sie die Reduktionsoperation pay.mean() oder numpy.mean(pay), um ein Ergebnis für die gesamte Series zu erhalten. Eine Reduktion hat eine andere Ergebnisbedeutung als eine Transformation: Sie gibt einen aggregierten Wert zurück, nicht einen Wert pro Eingabezeile.
Ergebnisse prüfen und Benchmarks sorgfältig durchführen
Vergleichen Sie einen umgeschriebenen Ausdruck anhand repräsentativer Eingaben mit einer einfachen Referenzberechnung, bevor Sie ihn auf größere Daten anwenden. Das Beispiel prüft, ob die mit map und apply berechneten Werte mit den vektorisierten Werten übereinstimmen. Anschließend wird der Ausdruck mit einer manuell festgelegten Referenz-Series verglichen. Bei Gleichheitsprüfungen wird auch der Series-Index berücksichtigt. So lassen sich neben Wertunterschieden auch Abweichungen bei der Ausrichtung erkennen.
Fehlende Werte und Datentypen können das Verhalten beeinflussen. Rechenoperationen übernehmen fehlende Werte beispielsweise im Allgemeinen in das Ergebnis, während eine eigene Funktion anders damit umgehen kann. Auch Spalten mit Ganzzahlen, Gleitkommazahlen, nullable Datentypen oder Objekten können sich unterschiedlich verhalten. Prüfen Sie den Eingabedatentyp und legen Sie fest, wie fehlende Werte behandelt werden sollen, bevor Sie verschiedene Ansätze vergleichen.
Führen Sie Benchmarks nur durch, wenn die Leistung für Ihre Arbeitslast relevant ist. Vergleichen Sie gleichwertige Berechnungen mit denselben Eingabedaten, wärmen Sie den Code bei Bedarf auf, wiederholen Sie die Messungen und dokumentieren Sie Methode und Umgebung. Die Laufzeiten variieren je nach Hardware, pandas- und NumPy-Version, Datenmenge und Datentyp. Ein kleines Beispiel belegt daher keine allgemeine Geschwindigkeitssteigerung.