Polars vs. pandas: en hastighetsjämförelse, sedd genom Apple Silicon
Av Isak La Fleur Engdahl
När jag flyttar och formar om data i en migrering – lokalt eller i ett moln-warehouse – är körhastighet ingen fåfäng siffra. Den dyker upp på tre konkreta ställen:
- Kostnad. I de flesta molnens prismodeller är beräkningstiden notan. Snabbare bearbetning kan dessutom låta dig gå ner till en billigare tjänstenivå när resurserna är förallokerade.
- Färskhet. En ström som tar fem minuter att bearbeta gör att dashboardarna är minst fem minuter gamla. Även för timvisa batchjobb slår två minuter tjugo.
- Återkopplingsslinga. Ett jobb som blir klart på en minut låter mig fånga logikfel snabbt – och gör arbetet mindre smärtsamt.
Frågan den här jämförelsen tar sig an: över vanliga data engineering-uppgifter, är Polars faktiskt snabbare än pandas – och i så fall var?
Påståendet som prövas
Polars utlovar mer än 30x jämfört med pandas, med stöd av sin egen benchmark-svit med öppen källkod. Att publicera de mätningarna förtjänar beröm, men det finns en uppenbar intressekonflikt när ett verktygs egna upphovsmän utformar testet för både sitt eget verktyg och konkurrenten. Inte nödvändigtvis ohederligt – bara benäget att omedvetet välja en fördelaktig inramning. Den här övningen har därför två mål:
- Rimlighetspröva 30x-påståendet mot vanliga, realistiska uppgifter.
- Hitta vinsterna – visa vilka operationer som blir snabbare, så att den som funderar på att byta vet vad hen får.
Några medvetna avgränsningar: det här är ingen handledning, det rör inte PySpark (en distribuerad modell gör en rak jämförelse besvärlig), och det är ingen fullt reproducerbar vetenskaplig studie – det är en praktisk guide som siktar på grova, beslutsdugliga uppskattningar.
Upplägg
Dataset (båda från Kaggle):
- Litet / CSV: det klassiska Iris-datasetet – 5 kolumner, 150 rader. Den sortens lilla fil som vräker ut sig ur Excel-exporter och databasdumpar. Det belastar uppstartskostnaden.
- Stort / Parquet: Financial Transactions Dataset for Fraud Detection – 18 kolumner, 5 miljoner rader. Ungefär 796 MB som CSV, komprimerat till cirka 217 MB som Parquet med zstd. Det belastar skalbarheten. Det ligger i den nedre änden av "big data", vilket räcker gott för vårt syfte.
Fem uppgifter – två I/O, tre bearbetning:
- Läsa varje fil med standardinställningar (
read_csv/read_parquet). - Skriva ut varje fil igen med standardinställningar.
- Beräkna ett numeriskt uttryck som en ny kolumn.
- Filtrera rader på villkor.
- Gruppera på en kolumn och aggregera.
Testrigg: Apple MacBook Air (M4), 16 GB RAM, Python 3.14, Polars 1.41.2, pandas 3.0.3. Parquet skriven med zstd-komprimering. Tidtagning via timeit, median av 10 körningar. Ingen extern acceleration för pandas – båda biblioteken mätta ur kartongen, så som de flesta team faktiskt kör dem.
Resultat
Bilden är mer nyanserad än marknadsföringen antyder. Polars vinner de flesta uppgifter, och försprånget är störst precis där det betyder mest – de tunga operationerna på det stora datasetet. Men det är ingen ren genomklappning: på lätt elementvis beräkning och på läsning är det i stort sett oavgjort, och på ett par av uppgifterna på det lilla datasetet är pandas till och med snäppet snabbare.
| Uppgift | Dataset | pandas | Polars | Polars försprång |
|---|---|---|---|---|
| Läsa | Iris | 0,20 ms | 0,06 ms | ~3,1x |
| Läsa | Transaktioner | 166,87 ms | 139,94 ms | ~1,2x |
| Skriva | Iris | 0,30 ms | 0,21 ms | ~1,4x |
| Skriva | Transaktioner | 2,12 s | 0,48 s | ~4,4x |
| Numeriskt uttryck | Iris | 0,11 ms | 0,01 ms | ~7,5x |
| Numeriskt uttryck | Transaktioner | 2,43 ms | 2,74 ms | ~0,9x (oavgjort) |
| Filtrera | Iris | 0,10 ms | 0,07 ms | ~1,5x |
| Filtrera | Transaktioner | 133,97 ms | 21,71 ms | ~6,2x |
| Gruppera | Iris | 0,12 ms | 0,14 ms | ~0,8x (pandas vinner) |
| Gruppera | Transaktioner | 87,98 ms | 7,77 ms | ~11,3x |
De som sticker ut: gruppering på stor data (~11,3x) och filtrering på stor data (~6,2x), med att skriva Parquet på en solid tredjeplats (~4,4x). Överraskningarna går åt andra hållet också: att läsa den stora Parquet-filen är i princip oavgjort (~1,2x), och det enkla numeriska uttrycket är ett nollsummespel – på den lilla tabellen vinner pandas till och med grupperingen rakt av. Vinsterna är alltså verkliga men koncentrerade: de bor i det parallelliserbara tunga lyftet, inte i I/O eller trivial elementvis matematik.
Varför Apple Silicon formar de här siffrorna
Tiderna kommer direkt från M4:an, och några av chippets egenskaper förklarar tabellens form:
- Båda biblioteken kör nativt på Apple Silicon (arm64). Polars och pandas levererar båda nativa ARM-wheels, så det finns ingen Rosetta-straffavgift – de absoluta tiderna gynnas av moderna kärnor, hög minnesbandbredd och en mycket snabb SSD.
- Polars använder varje kärna; pandas gör det mestadels inte. Polars är flertrådat i Rust och sprider parallelliserbart arbete över alla M4:ans kärnor, medan pandas kör de här operationerna i stort sett enkeltrådat ur kartongen. Det är precis därför filtrering och gruppering visar de största gapen ovan – de parallelliserar utmärkt.
- Läsningen rör sig knappt, och det är logiskt. Att läsa Parquet domineras av I/O och av Arrows avkodningsväg, som pandas redan kör via en flertrådad pyarrow-läsare. När båda biblioteken slår mot samma snabba Arrow-maskineri är M4:ans SSD och minnesbandbredd flaskhalsen, inte dataframe-biblioteket – så gapet krymper till ~1,2x. Den stora vinsten på skrivning är baksidan av samma mynt: där drar Polars Rust-skrivare ifrån pandas.
- Enhetligt minne hjälper stordatafallet. M4:ans enhetliga minne med hög bandbredd är en verklig tillgång för transaktionsliknande arbetslaster, där genomströmning betyder mer än ren klockfrekvens.
- RAM är variabeln att hålla ögonen på. Den ~217 MB stora Parquet-filen packas upp och expanderar i minnet, och mellanliggande kopior under transformationerna summerar sig. Den ryms bekvämt i 16 GB för det här datasetet, men skala upp till flera filer eller mycket bredare tabeller och 16 GB är där du börjar känna trycket – precis där Polars lata API (nedan) gör nytta.
Asterisken: Polars hålls tillbaka här
Varje test ovan mäter en enda operation isolerat. Så fungerar inte verkliga pipelines – man kedjar oftast ihop många transformationer. Polars har ett lat API som tittar på hela kedjan och optimerar den innan en enda rad körs. Eftersom den här jämförelsen bara tog tid på engångsoperationer kom den fördelen aldrig fram. I realistiska flerstegspipelines vore gapet sannolikt större, inte mindre – och på en minnesbegränsad maskin hjälper lat evaluering dig dessutom att slippa materialisera mellanliggande kopior du inte behöver.
Slutsats
- Inläsning: att skriva Parquet är klart snabbare på Polars (~4,4x på den stora filen), men läsning är i praktiken oavgjort (~1,2x) – båda biblioteken lutar sig mot samma snabba Arrow-läsare, så det är I/O, inte dataframe-motorn, som sätter takten.
- Bearbetning: det är här Polars förtjänar sitt rykte – gruppering (~11,3x) och filtrering (~6,2x) på det stora datasetet är avgörande segrar. Men ett rent elementvis numeriskt uttryck är ett nollsummespel (~0,9x), och på små tabeller är skillnaderna brus – pandas tar till och med den lilla grupperingen.
- Sammantaget: Polars vinner de operationer som dominerar verklig ETL-kostnad – gruppering, filtrering, skrivning – ofta med bred marginal. Det är inte genomgående snabbare: på läsning och trivial beräkning ligger de två jämsides.
Och – inget här kommer i närheten av de utlovade 30x. Även bästa fallet toppar runt 11x, på en enda operation. På vanliga uppgifter och realistisk hårdvara ser den rubriksiffran optimistisk ut. Den ärliga slutsatsen är mer jordnära: Polars är märkbart snabbare där det räknas, inte långsammare någonstans som spelar roll, och det är inte svårare att arbeta med än pandas.
Praktisk rekommendation: för ditt nästa data engineering-projekt där datan ryms i minnet – vilket, på en modern 16 GB-laptop, täcker en hel del mark – välj Polars som standard. De tunga operationerna som driver din körtid blir märkbart snabbare, resten är minst lika snabbt, och det lata API:et ger dig svängrum när pipelines och datamängder växer.
Återskapa det själv
Vill du köra samma fem uppgifter på din egen maskin? Hämta skriptet – det är exakt koden bakom den här artikeln:
polars_vs_pandas_benchmark.pyDet genererar ersättningsdataset som standard, så det körs utan några nedladdningar – eller peka det mot de riktiga Kaggle-filerna för att återskapa tabellen ovan. Parquet skrivs med zstd; skriptet upptäcker automatiskt vilka kolumner som ska beräknas och grupperas på (eller så namnger du dem):
pip install numpy pandas polars pyarrow
# Syntetisk data, direkt ur kartongen:
python polars_vs_pandas_benchmark.py
# De riktiga dataseten som används här (Iris CSV + Transactions Parquet):
python polars_vs_pandas_benchmark.py \
--iris iris.csv \
--transactions financial_fraud_detection_dataset.parquet \
--tx-num-col amount --tx-group-col merchant_category \
--compression zstd
Här är den faktiska körningen bakom tabellen ovan – riktig Kaggle-data, median av 10 körningar via timeit, zstd-Parquet, på M4:an:
pandas 3.0.3 · polars 1.41.2 · numpy 2.4.6
Timing: median of 10 runs via timeit · Parquet codec: zstd
=== Small / CSV (Iris) ===
Task pandas Polars Advantage
----------------------------------------------------------
Read (read_csv) 0.20 ms 0.06 ms 3.1x
Write 0.30 ms 0.21 ms 1.4x
Numeric expr 0.11 ms 0.01 ms 7.5x
Filter 0.10 ms 0.07 ms 1.5x
Group by 0.12 ms 0.14 ms 0.8x
=== Large / Parquet (Transactions) ===
rows=5,000,000 cols=18 numeric='amount' group='merchant_category'
Read (read_parquet) 166.87 ms 139.94 ms 1.2x
Write 2.12 s 484.49 ms 4.4x
Numeric expr 2.43 ms 2.74 ms 0.9x
Filter 133.97 ms 21.71 ms 6.2x
Group by 87.98 ms 7.77 ms 11.3x
En kommentar om siffrorna: tiderna varierar lite mellan körningar, och de beror på din hårdvara, din datas form och Parquet-codec:en – på en svagare maskin, eller med en bredare tabell, flyttar sig de absoluta tiderna. Det som är stabilt är resultatets form: Polars drar ifrån på gruppering, filtrering och skrivning, medan läsning och trivial elementvis beräkning ligger nära varandra.
Nyfiken på hur det ser ut på din egen data och hårdvara? Hör av dig – eller kör bara skriptet ovan och se dina faktiska tider.