
Nu het datascience-landschap steeds complexer wordt en er elke dag nieuwe technologieën opduiken, is de keuze van de juiste gereedschapskist cruciaal voor je project. Hoe complexer het project, hoe voorzichtiger je moet zijn bij het kiezen van je tools, want je keuzes hebben grote impact op de ontwikkeling en uiteindelijk het succes van je project.
Werk je aan een datascience-project, dan gaan ontwerpkeuzes veel verder dan het Python vs R-debat. Het gaat ook om de libraries die je gebruikt zodra je de programmeertaal of -talen hebt gekozen waarop je project gebaseerd is.
Voor Python in data science is pandas de de facto standaardtool voor datamanipulatie. De redenen om pandas te gebruiken zijn talrijk en overtuigend, maar er zijn ook beperkingen die tot flinke bottlenecks kunnen leiden in je projecten. Pandas staat met name bekend om zijn beperkte prestaties bij grote datasets.
Om deze problemen aan te pakken, heeft pandas onlangs versie 2.0 uitgebracht, met belangrijke wijzigingen en prestatieverbeteringen (bekijk dit artikel voor alles wat je moet weten over pandas 2.0).
Ondertussen zijn er binnen het Python-ecosysteem nieuwe alternatieven verschenen die de dominantie van pandas uitdagen. Een van de populairste is polars, een op Python en Rust gebaseerde library voor snellere data-analyse.
In dit artikel analyseren we de verschillen tussen pandas 2.0 en polars voor datamanipulatie. We beginnen met strategieën om de rekenprestaties te verbeteren en eindigen met een reeks tests om de prestaties van beide tools te vergelijken. Aan de slag!
Hoe kies je tussen pandas en polars
Er is geen enkele technologie die in absolute zin het best is voor alle problemen en situaties die zich tijdens je datascience-workflows kunnen voordoen. Je moet verschillende factoren afwegen voordat je een keuze maakt. Dit zijn enkele van de meest relevante factoren om te overwegen:
- Rekenprestaties. Vuistregel: hoe groter en complexer het project, hoe meer je high-performance tools moet overwegen om rekenbottlenecks te voorkomen.
- Aansluiting op je technologiestack. Tools in een datascience-project werken zelden op zichzelf. Ze werken juist samen met andere tools in de stack. Wees je dus bewust van de synergieën en de match tussen technologieën voordat je kiest.
- Codecompatibiliteit. Een nieuwe technologie kiezen gaat ook over compatibiliteit en efficiëntie van code. Als het adopteren van een nieuwe tool betekent dat je code in bestaande projecten moet herschrijven, neem dat dan mee in je afweging.
- Populariteit. De populariteit van een tool is een indicatie van hoeveel mensen deze gebruiken. Dat kan handig zijn bij het aannemen van nieuwe developers of het oplossen van codevragen op platforms als Stack Overflow.
Hoe kun je de prestaties van datamanipulatie verbeteren?
In deze sectie behandelen we de belangrijkste technieken die kunnen helpen om de prestaties van datamanipulatie te verhogen.
Kopiëren verminderen met copy-on-write
In traditionele tools voor datamanipulatie leidt elke bewerking tot het maken van een nieuwe kopie van de volledige dataset. Dit kan problematisch zijn voor je geheugengebruik bij grote datasets.
Copy-on-write is de meest gebruikte techniek om dit op te lossen. In essentie is copy-on-write een techniek voor resourcebeheer waarmee je een "duplicaat"- of "kopie"-operatie op wijzigbare resources efficiënt kunt implementeren. Dat betekent dat als een dataset gedupliceerd wordt maar niet (volledig) gewijzigd, het niet nodig is een nieuwe resource aan te maken. In plaats daarvan kunnen de geheugenresources worden gedeeld tussen de kopie en het origineel.
Parallelle berekening
Een van de belangrijkste nadelen van pandas is dat het single-threaded is, waardoor het geen gebruik kan maken van parallelle rekentechnieken die nu gangbaar zijn in data science. Parallel rekenen gebeurt vooral via multi-core machines of distributed computing (dus een groep computers die samenwerkt in een cluster).
Neem het volgende voorbeeld met de populaire groupby-functie. Als je de gemiddelde leeftijd van basketballers per team wilt berekenen, kun je parallelle berekening gebruiken om de berekening van het gemiddelde van elke groep aan één core of machine toe te wijzen in plaats van ze één voor één te berekenen. Zo verhoog je de performance.

Data-import optimaliseren
Het startpunt van data-analyse is meestal het inlezen van de datasets die je wilt bestuderen. Dit is echter vaak een bottleneck in dataprojecten met grote datasets. Hier zijn enkele technieken die kunnen helpen om prestaties te verbeteren bij het inlezen van data:
- Data in stukken lezen (chunking). In plaats van het hele bestand te lezen, kun je het opdelen in kleine stukjes, oftewel chunks. Deze techniek maakt sneller importeren mogelijk en vermindert tegelijkertijd het geheugen dat nodig is om alles tegelijk op te slaan.
- Alleen vereiste kolommen lezen. Soms weet je vooraf welke kolommen je nodig hebt voor je analyse. In plaats van de volledige dataset te lezen, kun je vooraf filteren en alleen de benodigde kolommen inlezen.
- Downcasten van datatypes. Tools als pandas hebben een standaardgedrag bij het toewijzen van datatypes aan geïmporteerde kolommen. Soms zijn er andere types beschikbaar die minder geheugen vereisen zonder informatieverlies. Downcasten is het proces waarbij je datatypes wijzigt naar het kleinste type dat de waarde nog aankan.
Lazy evaluation en query planning
De volgorde waarin bewerkingen worden uitgevoerd, kan invloed hebben op de prestaties. Vaak kun je sommige berekeningen herschikken en zo efficiënter tot hetzelfde antwoord komen.
Er zijn twee strategieën om dit te bereiken: lazy evaluation en query planning. De eerste verwijst naar het uitstellen van berekeningen tot het echt nodig is. De tweede is het proces van het vinden van de meest efficiënte manier om meerdere datamanipulaties uit te voeren, gegeven een set verschillende queries. Daarbij wordt meestal een query optimizer gebruikt.
Out-of-core processing
Tools als pandas slaan hele datasets in je geheugen op. Dat kan lastig zijn als je werkt met grote datasets die niet in het geheugen van je computer passen of bij geheugenintensieve bewerkingen.
Hier komt out-of-core computing in beeld. Simpel gezegd verwijst out-of-core processing naar extern geheugen (bijv. een externe schijf) dat data opslaat die anders niet in je hoofdgeheugen zou passen. Out-of-core processing laat je toe om extern opgeslagen data in stukken te verwerken, zodat je uiteindelijk dezelfde resultaten krijgt als wanneer je het hele proces op je computer zou draaien.
Wat zijn high-performance alternatieven voor pandas?
Dit artikel focust op de vergelijking pandas 2.0 vs polars, maar it is ook de moeite waard om andere tools te noemen die aan je behoeften als pandas-alternatief kunnen voldoen. Dit zijn enkele veelbelovende tools:
- Koalas. Een pandas-API boven op PySpark. Gebruik je Spark, overweeg dan deze tool.
- Vaex. Een pandas-API voor out-of-memory-berekeningen, ideaal om grote tabeldata te analyseren met een miljard rijen per seconde.
- Modin. Een pandas-API voor parallel programmeren, gebaseerd op Dask- of Ray-frameworks voor big-dataprojecten. Gebruik je Dask of Ray, dan is Modin een sterke troef.
- cuDF. Onderdeel van het RAPIDS-project; cuDF is een pandas-achtige API voor GPU-berekeningen die leunt op NVIDIA GPU’s of andere onderdelen van RAPIDS voor hoge-snelheidsdatamanipulatie.
Waarom kiezen voor polars?
Pandas is de go-to optie voor dataprofessionals die Python gebruiken, maar zoals uitgelegd heeft het enkele belangrijke beperkingen bij het werken met grote datasets. De kernmissie van polars is het bieden van een razendsnelle dataframe-library die alle problemen van pandas adresseert.
Geschreven in Rust (een krachtige programmeertaal die C/C++-prestaties levert en volledige controle geeft over prestiekritieke delen in een query-engine), integreert polars state-of-the-art methodologieën om de performance te verhogen, ontworpen om:
- Parallelle berekening te verbeteren zodat je alle beschikbare cores van je machine kunt benutten.
- Queries te optimaliseren om onnodig werk/geheugentoewijzingen te verminderen via lazy evaluation en query planning.
- Opslagprestaties te verbeteren met copy-on-write-semantiek en Apache Arrow.
- Veel grotere datasets aan te kunnen via out-of-core mogelijkheden met de streaming-API.
Tot slot is een belangrijk kenmerk van polars dat de syntax behoorlijk lijkt op die van pandas en dezelfde bouwstenen deelt, zoals Series en DataFrames. Dat maakt de overstap naar polars een stuk eenvoudiger.
Hoe reageert pandas op de toegenomen concurrentie met pandas 2.0?
Om de prestatieproblemen aan te pakken en de druk van concurrenten het hoofd te bieden, heeft pandas onlangs de langverwachte versie 2.0 uitgebracht. Als grote update biedt pandas 2.0 een reeks nieuwe features. Er zijn ook gedwongen deprecations, wat resulteert in API-wijzigingen.
De nieuwe PyArrow-backend is de grote troef van het nieuwe pandas om de prestatiebeperkingen aan te pakken. Gebruikers kunnen nu kiezen tussen de traditionele NumPy-backend of de gloednieuwe PyArrow-backend. PyArrow is een Python-library die een interface biedt voor het verwerken van grote datasets met Arrow-geheugenstructuren.
pd.read_csv(my_file, engine='pyarrow')
Een andere belangrijke verbetering is de opname van verschillende copy-on-write-vernieuwingen die bedoeld zijn om prestaties te verbeteren door geheugenbronnen te besparen.
Daardoor hebben veel pandas-bewerkingen nu een standaardparameter “copy” die een luie kopie teruggeeft van basisobjecten zoals series en dataframes, in plaats van identieke, gecachte kopieën van die objecten.
Het is nog te vroeg om te weten of de mogelijkheden van pandas de prestatieproblemen zullen oplossen. Zelfs als andere tools het voorbijstreven, zijn er nog steeds goede redenen om pandas te blijven gebruiken: je hoeft geen bestaande code te herschrijven of nieuwe code te leren, want je gebruikt het waarschijnlijk al.
pandas 2.0 vs polars: vergelijkingskader
Nu je de theorie kent, is het tijd om je handen vuil te maken. In de volgende secties voeren we een reeks tests uit om de prestaties van pandas 2.0 vs polars te vergelijken. Onze benchmark is de tijd die nodig is om een taak uit te voeren. Hiervoor gebruiken we de module time, die een eenvoudige manier biedt om uitvoeringstijden te berekenen.
Naast de prestatietests analyseren we de codecompatibiliteit van polars met pandas (dus: hoeveel code moet je aanpassen als je wilt overstappen op polars?).
De dataset
We testen de prestaties van pandas 2.0 vs polars op een fictieve dataset met uurlijkse verkopen van een bedrijf met kantoren in verschillende landen in de periode 1980-2022. Om de benchmarkanalyse complexer te maken, voegen we willekeurige missende waarden toe.
In totaal omvat de dataset meer dan 22 miljoen rijen en meer dan 1,6 GB aan geheugen, genoeg om pandas stevig onder druk te zetten. De volledige code voor de benchmarktests vind je in dit DataLab-werkboek.

Importtest
Laten we beginnen met de vergelijking van de prestaties van pandas 2.0 en polars bij het importeren van data. Polars profileert zich expliciet met sterke prestaties bij het importeren uit CSV. Klopt dat?
We voeren een test uit om te kijken hoe lang het duurt voor pandas en polars om een subset van kolommen en rijen te lezen. Stel bijvoorbeeld dat je alleen de verkopen van het kantoor in Frankrijk wilt analyseren. Met pandas moet je alle rijen inlezen en daarna filteren om de ongewenste rijen te verwijderen. We gebruiken de gloednieuwe methode .query() om dat te doen. Om het gedrag van pandas 2.0 te testen, importeren we de CSV zowel met de traditionele numpy-engine als met de nieuwe pyarrow-engine.
Polars daarentegen biedt de methode filter(), die je met voorwaarden kunt combineren om alleen de rijen van jouw interesse te lezen.
# pandas query
df_pd = pd.read_csv("./example.csv", engine="pyarrow")
df_pd = df_pd[['id', 'date', 'office', 'sales']]
df_pd = df_pd.query("office=='France'")
# polars filter
df_pl = pl.read_csv('example.csv').filter(
(pl.col('office') == 'France'))
df_pl.select(pl.col(['id', 'date', 'office', 'sales']))
Wanneer we de test uitvoeren, presteert polars aanzienlijk beter dan pandas, zoals te zien in de grafiek. Verrassend genoeg gaf de pyarrow-engine geen betere resultaten dan de standaard numpy-engine.

Qua syntax heeft polars duidelijk dezelfde uitstraling als pandas, met functies als pl.read_csv() die pandas perfect spiegelen. Toch werken de twee libraries onder de motorkap verschillend, wat onvermijdelijk tot syntactische verschillen leidt, zoals te zien is bij de methoden query() vs filter().
Groupby-test
Groupby-bewerkingen lenen zich goed voor parallelisatie. Laten we kijken hoe pandas en polars zich gedragen in verschillende gegroepeerde aggregaties. We berekenen met name het gemiddelde en de mediaan van de verkopen per kantoor en maand.
df_pd.groupby([df_pd.office, df_pd.date.dt.month])['sales'].agg('mean') # pandas groupby mean
df_pl.groupby([pl.col('office'), pl.col('date').dt.month()]).agg([pl.mean('sales')]) # polars groupby mean

df_pd.groupby([df_pd.office, df_pd.date.dt.month])['sales'].agg('median') # pandas groupby median
df_pl.groupby([pl.col('office'), pl.col('date').dt.month()]).agg([pl.median('sales')]) pandas groupby median

De resultaten laten zien dat polars bij groupby- en aggregatieberekeningen beter presteert dan pandas. Opnieuw lijkt de syntax van polars op die van pandas.
Rolling-statistiektest
Een andere geschikte bewerking om de prestaties van pandas en polars te testen zijn rolling statistics. Het optimaliseren van dit soort berekeningen vergt veel lastige algoritmische arbeid. Laten we kijken hoe ze zich gedragen bij het berekenen van een rollend gemiddelde van verkopen per dag.
# pandas rolling mean
df_pd['sales'].rolling(1440, min_periods=1).mean()
# polars rolling mean
df_pl['sales'].rolling_mean(1440, min_periods=1)
Opnieuw is polars de winnaar. Let op het subtiele verschil in syntax. Polars heeft de methode rolling_mean(), terwijl pandas de methode rolling() heeft, die je moet combineren met andere methoden, zoals mean(), om hetzelfde resultaat te krijgen.

Samplingtest
De hele populatie bestuderen om een fenomeen te analyseren is meestal niet mogelijk. Daarom is steekproeven nemen een van de meest voorkomende taken in statistiek en data science. Dit houdt in dat je willekeurige steekproeven neemt met Monte Carlo-simulatie-technieken, zoals bootstrapping en permutatie. Deze bewerking vereist echter ook veel kopiëren van variabelen, wat een uitdaging kan zijn als je onvoldoende rekenbronnen hebt.
Laten we kijken hoe pandas en polars werken bij het uitvoeren van een bootstrap, oftewel resampling met teruglegging. We schatten het gemiddelde van de verkopen in 10.000 steekproeven van elk 1.000 datapunten.
#pandas bootstrap
simu_weights = []
for i in range(10000):
bootstrap_sample = random.choices(df_pd['sales'], k=1000)
simu_weights.append(np.nanmean(bootstrap_sample))
#polars bootstrap
simu_weights = []
for i in range(10000):
bootstrap_sample = df_pl['sales'].sample(n=1000,with_replacement=True)
simu_weights.append(bootstrap_sample.mean())
Bij het uitvoeren van de bootstrap-sampling is polars bijna 5 keer sneller dan pandas.
Wat syntax betreft leunt pandas op numpy voor samplingoperaties, terwijl polars een ingebouwde, handige methode sample() biedt.

Samengestelde manipulaties
Voor de laatste test voeren we een reeks gekoppelde datamanipulaties uit. Dit hoort bij het dagelijks werk van dataprofessionals. Toch zijn datataken met veel stappen makkelijk op een computationeel suboptimale manier te schrijven.
Stel dat het Italiaanse kantoor van het fictieve bedrijf overweegt om enkele stagiairs van 2022 aan te nemen na afloop van hun stageperiode. Ons doel is te analyseren welke stagiairs in 2022 de tien grootste verkooptransacties hebben gedaan, zodat we die info kunnen gebruiken om de beste kandidaten te kiezen.
Daarvoor moeten we onze dataset joinen met een tweede dataset, “italy_2022”, met informatie over de persoon die elke transactie in 2022 heeft uitgevoerd. De kolom “id” is de gemeenschappelijke kolom van beide datasets.

# pandas compound operations
df_pd.merge(italy_2022, on='id').query("responsibility =='Sales Intern'").sort_values('sales', ascending=False).head(10)[['name','surname','sales','sex']]
#polars compound manipulations
df_pl.join(italy_2022_pl, on="id").filter(pl.col('responsability') == 'Sales Intern').sort('sales',descending=True).head(10).select(pl.col(['name','surname','sales','sex']))

Zoals in alle voorgaande tests verslaat polars pandas qua prestaties. In deze test lijkt de join-bewerking de grootste struikelblok voor pandas. Polars is daarentegen veel efficiënter en heeft minder dan twee seconden nodig om alle ketentaken te voltooien.
pandas 2.0 vs polars-vergelijkingstabel
We hebben de bovenstaande tests samengevat in een tabel voor een snelle vergelijking:
|
Test |
Pandas 2.0 |
Polars |
Winnaar |
Syntactische gelijkenis |
|
Importtest |
Leest alle rijen en filtert daarna ongewenste rijen met de .query()-methode |
Leest direct alleen de relevante rijen met de methode filter() |
Polars (betere prestaties) |
Gelijkend, maar met verschillen door de onderliggende implementatie (.query() vs filter()) |
|
Groupby-test |
Gebruikt .groupby() voor aggregaties zoals gemiddelde en mediaan van verkopen per kantoor en maand |
Hetzelfde als pandas, maar met betere prestaties |
Polars (betere prestaties) |
Gelijkend |
|
Rolling-statistiektest |
Gebruikt de methode rolling() in combinatie met andere methoden, zoals mean(), voor rollende gemiddelden |
Gebruikt de methode rolling_mean() voor rollende gemiddelden |
Polars (betere prestaties) |
Gelijkend, maar met kleine verschillen (.rolling().mean() vs rolling_mean()) |
|
Samplingtest |
Gebruikt numpy voor bootstrap-sampling |
Gebruikt ingebouwde sample()-methode voor bootstrap-sampling |
Polars (bijna 5 keer sneller) |
Verschillend: pandas leunt op numpy, polars heeft ingebouwde methoden |
|
Test samengestelde manipulaties |
Voert een join uit met een andere dataset en sorteert en selecteert daarna data |
Voert dezelfde taken uit maar efficiënter |
Polars (aanzienlijk sneller) |
Gelijkend, maar met kleine verschillen (merge().query().sort_values().head() vs join().filter().sort().head().select()) |
Ga een stap verder
Gefeliciteerd dat je het einde van deze tutorial hebt gehaald. Volgens de tests presteert polars aanzienlijk beter dan pandas 2.0 in bijna alle tests. Hoewel dit een echte bedreiging vormt voor zijn dominantie, heeft pandas nog steeds het voordeel dat het de standaardoptie is voor datamanipulatie in Python, met alle voordelen van een grotere gebruikerscommunity.
Werk je met grote datasets, dan is prestatieverbetering een must. DataCamp helpt je daarbij. Hier is een lijst met cursussen die je helpen om je rekenprestaties naar een hoger niveau te tillen:
Ik ben een freelance data-analist en werk samen met bedrijven en organisaties wereldwijd aan datascienceprojecten. Ook geef ik les in data science en heb ik meer dan twee jaar ervaring als docent. Ik schrijf regelmatig artikelen over data science in het Engels en Spaans; sommige daarvan zijn gepubliceerd op bekende platforms zoals DataCamp, Towards Data Science en Analytics Vidhya. Als data scientist met een achtergrond in politicologie en recht wil ik werken op het snijvlak van openbaar beleid, recht en technologie. Ik zet de kracht van ideeën in om innovatieve oplossingen en verhalen te ontwikkelen die helpen bij het aanpakken van urgente uitdagingen, met name de klimaatcrisis. Ik beschouw mezelf als autodidact, een eeuwige leerling en een groot voorstander van multidisciplinariteit. Het is nooit te laat om nieuwe dingen te leren.

