Polars und pandas: Was ist der Unterschied?
Wenn Sie im vergangenen Jahr die Entwicklung bei Python-Dataframes verfolgt haben, haben Sie mit Sicherheit schon von Polars gehört, der leistungsstarken Dataframe-Bibliothek für große Datensammlungen.

Polars in DataSpell ausprobieren
Im Gegensatz zu anderen Bibliotheken für große Datensammlungen wie Spark, Dask und Ray ist Polars für die Nutzung auf einem einzigen Rechner konzipiert, weswegen es oft mit pandas verglichen wird. Polars unterscheidet sich jedoch in wichtigen Punkten von pandas, unter anderem in der Art und Weise der Arbeit mit Daten sowie den optimalen Einsatzgebieten. Im folgenden Artikel gehen wir auf die technischen Details ein, die diese beiden Dataframe-Bibliotheken voneinander unterscheiden, und wir werfen einen Blick auf die Stärken und Beschränkungen beider Bibliotheken.
Um mehr über das Thema zu erfahren, sehen Sie sich unten unser Interview mit Polars-Schöpfer Ritchie Vink an!
Warum Polars statt pandas verwenden?
Mit einem Wort: Performance. Polars wurde von Grund auf für Schnelligkeit entwickelt, sodass es gängige Operationen etwa 5- bis 10-mal schneller als pandas ausführt. Darüber hinaus ist der Speicherbedarf von Operationen in Polars deutlich geringer als bei pandas: pandas benötigt für die Durchführung von Operationen etwa 5- bis 10-mal mehr Arbeitsspeicher als die Größe des Datensatzes, während Polars sich mit dem 2- bis 4-Fachen genügt.
Hier erhalten Sie einen Eindruck davon, wie Polars im Vergleich zu anderen Dataframe-Bibliotheken abschneidet. Wie Sie sehen können, ist Polars bei gängigen Operationen 10- bis 100-mal schneller als pandas und eine der schnellsten Dataframe-Bibliotheken überhaupt. Außerdem kann es größere Datensammlungen als pandas verarbeiten, bevor ihm der Arbeitsspeicher ausgeht.
Warum ist Polars so schnell?
Angesichts dieser äußerst beeindruckenden Ergebnisse fragen Sie sich vielleicht: Wie kann Polars trotz der Ausführung auf einem einzigen Rechner diese Performance erzielen? Bei der Entwicklung der Bibliothek wurde von Anfang an auf Leistung geachtet, und dabei kamen unterschiedliche Mittel zum Einsatz.
Geschrieben in Rust
Einer der bekanntesten Fakten über Polars ist, dass es in Rust geschrieben ist, einer Low-Level-Sprache, deren Geschwindigkeit fast an C und C++ herankommt. pandas hingegen basiert auf Python-Bibliotheken, unter anderem auf NumPy. Zwar ist der Kern von NumPy in C geschrieben, es wird aber trotzdem durch inhärente Probleme eingebremst, die mit der Art und Weise zu tun haben, wie Python bestimmte Typen im Arbeitsspeicher handhabt – zum Beispiel Zeichenfolgen für Kategoriedaten. Dies führt zu einer schlechten Leistung beim Umgang mit diesen Typen (weitere Details finden Sie in einem fantastischen Blogartikel von Wes McKinney).
Ein weiterer Vorteil von Rust ist, dass es sichere Nebenläufigkeit ermöglicht, d. h. es ist darauf ausgelegt, Parallelität so vorhersehbar wie möglich zu machen. Dadurch kann Polars auch bei komplexen Abfragen mit mehreren Spalten alle Kerne Ihres Systems nutzen – nicht umsonst nannte Ritchie Vink Polars „hochgradig parallel“. Dies verleiht Polars einen enormen Leistungsvorteil gegenüber pandas, das zur Ausführung von Operationen nur einen Kern verwendet. In diesem hervorragenden Vortrag auf der diesjährigen PyCon DE geht Nico Kreiling genauer darauf ein, wie Polars dies erreicht.
Basierend auf Arrow
Ein weiterer Faktor, der zur beeindruckenden Performance von Polars beiträgt, ist das sprachunabhängige Speicherformat Apache Arrow. Arrow wurde von Wes McKinney als Antwort auf viele Probleme entwickelt, die er bei pandas bei explodierenden Datenmengen erkannte. Es dient auch als Backend für pandas 2.0, eine leistungsfähigere pandas-Version, die im März dieses Jahres veröffentlicht wurde. Die Arrow-Backends der Bibliotheken unterscheiden sich jedoch leicht: Während pandas 2.0 auf PyArrow aufbaut, hat das Polars-Team seine eigene Arrow-Implementierung gebaut.
Einer der Hauptvorteile beim Aufbau einer Datenbibliothek auf der Basis von Arrow ist die Interoperabilität. Arrow wurde entwickelt, um das Format der In-Memory-Daten über Bibliotheken hinweg zu standardisieren, und wie Sie unten sehen können, wird es bereits von mehreren wichtigen Bibliotheken und Datenbanken verwendet.

Diese Interoperabilität erhöht die Performance, da die Daten nicht mehr in unterschiedliche Formate konvertiert werden müssen, wenn sie von einem Pipeline-Schritt zum nächsten weitergeleitet werden (anders ausgedrückt ist es nicht mehr notwendig, die Daten zu serialisieren und zu deserialisieren). Es ist auch speichereffizienter, da zwei Prozesse dieselben Daten gemeinsam nutzen können, ohne eine Kopie erstellen zu müssen. Da die Serialisierung/Deserialisierung bei Daten-Workflows ca. 80–90% des Rechenaufwands ausmacht, verhilft das universelle Arrow-Datenformat Polars zu erheblichen Leistungsgewinnen.
Arrow bietet außerdem integrierte Unterstützung für eine breitere Palette von Datentypen als pandas. Da pandas auf NumPy basiert, kann es hervorragend mit Ganzzahl- und Fließkommazahl-Spalten umgehen, hat jedoch Schwierigkeiten bei anderen Datentypen. Im Gegensatz dazu bietet Arrow umfassende Unterstützung für Spalten mit Datums-, booleschen und Binärwerten und sogar komplexe Spaltentypen, etwa solche, die Listen enthalten. Außerdem kann Arrow nativ mit fehlenden Daten umgehen, während in NumPy ein Workaround erforderlich ist.
Und schließlich verwendet Arrow eine spaltenbasierte Datenspeicherung. Dies bedeutet, dass unabhängig vom Datentyp alle Spalten in einem kontinuierlichen Speicherblock gespeichert werden. Dies vereinfacht nicht nur die Parallelisierung, sondern beschleunigt auch den Datenabruf.
Abfrageoptimierung
Ein weiterer Kernaspekt der Polars-Performance ist die Art und Weise, wie Code ausgewertet wird. pandas setzt standardmäßig die sogenannte Eager Execution ein, die Operationen werden also in der Reihenfolge ausgeführt, in der Sie sie geschrieben haben. Im Gegensatz dazu ist Polars in der Lage, neben Eager Execution auch Lazy Execution zu verwenden, wobei ein Abfrageoptimierer alle erforderlichen Operationen auswertet und den effizientesten Weg zur Ausführung des Codes findet. Dies kann unter anderem das Ändern der Ausführungsreihenfolge von Operationen oder den Verzicht auf redundante Berechnungen beinhalten. Nehmen wir zum Beispiel den folgenden Ausdruck, der jeweils den Mittelwert der Spalte Number1
für die Kategorien „A“ und „B“ in Category
berechnet.
( df .groupby(by = "Category").agg(pl.col("Number1").mean()) .filter(pl.col("Category").is_in(["A", "B"])) )
Bei Eager Execution wird die groupby
-Operation unnötigerweise für den gesamten DataFrame ausgeführt, und erst danach wird nach Category
gefiltert. Bei Lazy Execution kann der DataFrame gefiltert und groupby
nur auf die relevanten Daten angewendet werden.
Ausdrucksstarke API
Polars verfügt über eine extrem ausdrucksstarke API. Dies bedeutet, dass im Grunde jede benötigte Operation als Polars-Methode ausgedrückt werden kann. Im Gegensatz dazu müssen komplexere Operationen in pandas oft als Lambda-Ausdruck an die Methode apply
übergeben werden. Das Problem mit apply
ist, dass sie in einer Schleife auf die Zeilen des DataFrames angewendet wird, die Operation wird also nacheinander für jede Zeile ausführt. Durch die Verwendung eingebauter Methoden können Sie spaltenbasiert arbeiten und SIMD, eine andere Form der Nebenläufigkeit, nutzen.
Wann ist pandas zu bevorzugen?
Das bisher Gesagte klingt so eindrucksvoll, dass Sie sich wahrscheinlich fragen, warum Sie sich überhaupt noch mit pandas abgeben sollten. So einfach ist es jedoch nicht. Polars eignet sich zwar hervorragend für hocheffiziente Datentransformationen, ist aber derzeit nicht die optimale Wahl für die Datenexploration oder für den Einsatz in Pipelines für maschinelles Lernen (ML). In diesen Bereichen liegt pandas weiterhin vorn.
Einer der Gründe dafür ist, dass Polars zwar eine große Interoperabilität mit anderen Arrow-basierten Paketen bietet, aber noch nicht mit den meisten Python-Paketen zur Datenvisualisierung oder ML-Bibliotheken wie scikit-learn und PyTorch kompatibel ist. Die einzige Ausnahme ist Plotly, mit dem Sie Diagramme direkt aus Polars-DataFrames erstellen können.
Eine aktuell diskutierte Lösung wäre die Verwendung des Python-Dataframe-Austauschprotokolls in diesen Paketen, um ihnen die Unterstützung unterschiedlicher Dataframe-Bibliotheken zu ermöglichen. Dadurch würden Data-Science- und ML-Workflows nicht mehr durch pandas eingebremst werden. Dies ist jedoch eine relativ neue Idee, und die Umsetzung dieser Projekte wird einige Zeit dauern.
Tools für Polars und pandas
Nach all dem können Sie es sicher kaum erwarten, Polars eigenhändig auszuprobieren! Sowohl DataSpell als auch PyCharm Professional 2023.2 bieten hervorragende Werkzeuge für die Arbeit mit pandas und Polars in Jupyter-Notebooks. So stehen Ihnen insbesondere bei der Visualisierung von pandas- und Polars-DataFrames interaktive Funktionen zur Verfügung, mit denen Sie Ihre Daten viel schneller und bequemer erkunden können.
Zu meinen Lieblingsfunktionen gehören das Blättern durch alle Zeilen und Spalten des DataFrames, ohne dass diese abgeschnitten werden, Ein-Klick-Aggregationen von DataFrame-Werten sowie die Möglichkeit, DataFrames in einer Vielzahl von Formaten zu exportieren (einschließlich Markdown!).
Wenn Sie DataSpell noch nicht nutzen, können Sie es im Rahmen einer 30-tägigen Testphase ausprobieren, indem Sie dem nachstehenden Link folgen.
Autorin des Original-Blogposts: