Cursus
Als je, net als ik, regelmatig Python gebruikt voor data-analyse, valt al snel op dat CSV-bestanden inlezen een van de meest voorkomende taken is. Maar naarmate je datasets groeien, kan deze aanpak traag worden of veel geheugen vergen.
Polars is een snelle, moderne DataFrame-bibliotheek voor Python, ontworpen als high-performance alternatief voor Pandas. Het kan veel beter overweg met grote datasets dan traditionele tools, omdat het is gebouwd met een focus op snelheid en laag geheugengebruik.
De kernfunctie Polars pl.read_csv() biedt een eenvoudige manier om CSV-bestanden in een DataFrame te laden, met ingebouwde opties om parsing, datatypes en geheugengebruik te sturen.
In deze gids laat ik je zien hoe je CSV-bestanden leest, de parsing aanstuurt en met grote datasets werkt met de Polars pl.read_csv()-functie. Als je net begint, bekijk dan onze cursus Introduction to Polars om te leren hoe je data manipuleert en inzichten haalt met Polars.
Basisgebruik van pl.read_csv()
Voordat we verder gaan, bekijk onze tutorial Python Polars om te leren hoe je je omgeving inricht.
Laten we nu kijken hoe de functie pl.read_csv() werkt:
# import the module
import polars as pl
# Load CSV into a Polars DataFrame
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv")
# Preview first few rows
print(fuel_data.head())
In het bovenstaande voorbeeld leest Polars het bestand en laadt het in een DataFrame. De functie retourneert een Polars DataFrame, een tabelstructuur vergelijkbaar met wat je in pandas krijgt.
Standaard doet pl.read_csv() het volgende:
-
Gaat ervan uit dat de eerste rij kolomnamen bevat (
has_header=True) -
Leidt kolomdatatypes automatisch af
-
Gebruikt een komma (
,) als scheidingsteken -
Leest het hele bestand in het geheugen
Veelgebruikte parameters in pl.read_csv()
Nu je hebt gezien hoe pl.read_csv() data laadt, kijken we hoe je met de volgende parameters kunt bepalen hoe Polars je data parseert.
Bestandspad en bron
Polars laat je data uit verschillende bronnen laden. Je kunt een lokaal pad als string doorgeven, een Pathlib-object of zelfs een URL. In het volgende voorbeeld lezen we een groot csv-bestand vanaf het web met het bbp van verschillende landen in diverse jaren.
# Reading from a URL
url = "https://raw.githubusercontent.com/datasets/gdp/master/data/gdp.csv"
gdp_data = pl.read_csv(url)
Scheidingstekens
Niet alle CSV-bestanden gebruiken komma’s. Met het argument separator kun je tabs, puntkomma’s, pipes of andere tekens gebruiken. Het voorbeeld hieronder laat zien hoe je scheidingstekens opgeeft bij het inlezen van bestanden
# Reading a Semicolon-separated file
sales_data = pl.read_csv("2024_sales.csv", separator=";")
# Reading a Tab-separated file (TSV)
orders_data = pl.read_csv("all_orders.tsv", separator="\t")
Headers verwerken
Zoals we eerder zagen, gaat Polars ervan uit dat de eerste rij kolomnamen bevat. Als je bestand geen koprij heeft, gebruik dan de parameter has_header=False zoals hieronder. Polars kent dan automatisch kolomnamen toe zoals column_1, column_2, column_3, enzovoort.
# Load file without a header
orders_data = pl.read_csv("all_orders.csv", has_header=False)
Je kunt kolommen ook hernoemen door specifieke kolomnamen op te geven. Bijvoorbeeld:
# Providing specific column names
sales_data = pl.read_csv("sales_April.csv", new_columns=[
"OrderDate", "OrderNumber", "ProductKey", "SalespersonKey", "Salesperson"])
Encodering
Verschillende CSV-bestanden kunnen verschillende tekstcoderingen gebruiken. Als je vreemde tekens of fouten tegenkomt, specificeer dan de encoding:
# Load CSV into a Polars DataFrame
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv", encoding="utf8")
Andere veelgebruikte opties zijn ”latin1” en ”utf8-lossy”, die ongeldige tekens op een passende manier afhandelen.
Kolommen selecteren bij het lezen van CSV in Polars
Bij grote CSV-bestanden heb je vaak niet alle kolommen nodig. Met de parameter columns kun je alleen de kolommen laden die je nodig hebt.
# Load only specific columns
fuel_data = pl.read_csv("Fuel_Consumption_2000-2022.csv",
columns=["YEAR", "MAKE", "MODEL"]
)
Door de benodigde kolommen al bij het laden te selecteren, verminder je het geheugengebruik doordat overbodige data niet wordt ingelezen. Dit versnelt ook het inlezen en verbetert de algehele performance van je pipeline.
Datatypes (schema) verwerken in Polars CSV
Polars is sterk getypeerd, wat betekent dat elke kolom een consistent datatype moet hebben, zoals allemaal gehele getallen of allemaal strings.
Automatische type-inferentie
Standaard inspecteert Polars je data en bepaalt het automatisch de kolomtypes. Die methode werkt meestal goed, maar kan soms kolommen verkeerd interpreteren, bijvoorbeeld door ID’s als integers te zien in plaats van als strings.
Schema handmatig specificeren
Als je consistentie in je DataFrame wilt, is het beter om het dataschema handmatig te specificeren. Dit zorgt voor consistentie over meerdere bestanden heen en helpt typegerelateerde fouten in latere stappen te voorkomen.
Gebruik in de meeste gevallen schema_overrides om het datatype van specifieke kolommen vast te leggen, terwijl Polars de overige kolommen afleidt
import polars as pl
# Manually overriding specific data types
empl_data = pl.read_csv(
"all_employees.csv",
schema_overrides={
"id": pl.Int64,
"name": pl.String,
"age": pl.Int64,
"salary": pl.Float64
}
)
Of gebruik schema om de volledige structuur van het DataFrame te definiëren.
# Manually define the full schema
empl_data = pl.read_csv(
"all_employees.csv",
schema={
"id": pl.Int64,
"name": pl.String,
"age": pl.Int64,
"salary": pl.Float64
}
)
Omgaan met missende waarden in Polars CSV
Standaard detecteert Polars deze missende waarden automatisch en geeft ze weer als null. Soms worden missende waarden weergegeven met specifieke strings, zoals ”NA”, ”N/A” of ”missing”. Je kunt deze definiëren met null_values zodat ze als null worden behandeld.
# Treating "N/A" and "EMPTY" as nulls
survey_data = pl.read_csv(
"survey_results.csv",
null_values=["N/A", "EMPTY", "null"]
)
Door missende waarden goed te verwerken, zorg je voor consistente datatypes en voorkom je onjuiste berekeningen, waardoor je minder fouten krijgt tijdens analyse en modellering.
Grote CSV-bestanden lezen in Polars
Bij grote datasets die je beschikbare RAM overschrijden, blinkt Polars uit doordat het data kan verwerken zonder het hele bestand in één keer te laden.
Lazy loading met scan_csv()
In plaats van data meteen in het geheugen te laden zoals read_csv() doet, biedt Polars een lui alternatief, scan_csv(), dat een geoptimaliseerd queryplan opstelt en alleen de nodige bewerkingen uitvoert.
In het voorbeeld hieronder scant pl.scan_csv het CSV-bestand zonder het te laden, bouwt een query om alleen de kolommen “YEAR”, “MAKE” en “MODEL” te pakken waar het automerk “ACURA” is, en voert die query vervolgens uit. Zo wordt alleen de gefilterde datadeel in het geheugen geladen, in plaats van het hele bestand.
# Lazily reference the file (no data loaded yet)
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv")
fuel_consumption_filtered = fuel_consumption.select(
["YEAR", "MAKE", "MODEL"]).filter(pl.col("MAKE") == "ACURA")
# Execute the query and load only the required data
fuel_consumption_acura = fuel_consumption_filtered.collect()
Ik raad je aan scan_csv() te gebruiken wanneer:
- Je met grote bestanden werkt die niet comfortabel in het geheugen passen
- Je meerdere transformaties toepast, zoals filteren, selecteren en aggregeren
- Je optimalisatie van de query wilt vóór uitvoering
Streaming en geheugenefficiëntie
Polars kan ook streamen en data in chunks verwerken, waardoor het piekgeheugen constant blijft, ongeacht de bestandsgrootte.
Voor grote CSV-bestanden begin je met scan_csv() om een luie query te maken. Het bestand wordt niet volledig geladen wanneer scan_csv() wordt aangeroepen.
# Read data in chunks
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv",
low_memory=True)
Omdat de bovenstaande methode nog steeds read_csv gebruikt, is de beste aanpak om luie uitvoering te combineren met streaming.
In het voorbeeld hieronder verwerkt Polars het bestand pijplijngewijs, rij voor rij in batches, waarbij op elk moment alleen de gefilterde rijen (waar “CYLINDERS” > 3) in het geheugen blijven.
# Lazily reference the file (no data loaded yet)
fuel_consumption = pl.scan_csv("Fuel_Consumption_2000-2022.csv")
result = fuel_consumption.filter(pl.col("CYLINDERS") > 3)
# Stream execution instead of loading everything at once
fuel_consumption_high = result.collect(engine="streaming")
Performancevoordeel t.o.v. Pandas
Vergeleken met pandas presteert Polars vaak beter bij het lezen en verwerken van CSV’s, zoals we in de volgende sectie zullen zien.
Polars read_csv vs Pandas read_csv
De tabel hieronder vat het verschil samen tussen Polars en Pandas bij het lezen van csv in Python.
|
Aspect |
Polars |
Pandas |
|
Snelheid |
Sneller dankzij multithreading en geoptimaliseerde parsing |
Langzamer bij grote bestanden (meestal single-threaded) |
|
Geheugengebruik |
Kleinere footprint; ondersteunt lazy + streaming |
Laadt de volledige dataset meteen in het geheugen |
|
Syntaxis |
|
|
|
Uitvoeringsmodel |
Ondersteunt luie uitvoering ( |
Alleen eager (onmiddellijke) uitvoering |
|
Optimalisatie |
Ingebouwde query-optimalisatie (projectie, filtering) |
Beperkte automatische optimalisatie |
|
Beste usecase |
Grote datasets, performancekritische workflows |
Kleinere datasets, snelle analyse |
Ik raad je aan ons artikel over de verschillen tussen Pandas vs. Polars te lezen om te bepalen welk hulpmiddel het beste bij je analysetaken past.
CSV lezen uit verschillende bronnen
Zoals we eerder zagen, kun je met Polars CSV-bestanden uit verschillende bronnen lezen. In de bovenstaande voorbeelden liet ik zien hoe je CSV leest van lokale bestanden en URL’s.
Daarnaast kan Polars gecomprimeerde CSV-bestanden automatisch verwerken. Het volgende voorbeeld leest bijvoorbeeld data uit een .gzip-bestand.
# Read gzip-compressed CSV
census_data = pl.read_csv("2018_census.csv.gz")
Veelvoorkomende fouten en troubleshooting
Zelfs met een high-performance engine als Polars kun je nog steeds op problemen stuiten, vooral bij het lezen van een csv-bestand. Hieronder staan enkele veelvoorkomende issues die ik ben tegengekomen en hoe je ze oplost.
-
Encoderingfouten: Je kunt een fout zien zoals
UnicodeDecodeError, wat betekent dat het bestand geen UTF-8-encoding gebruikt, een probleem dat vaak voorkomt bij oudere bestanden of CSV’s die uit bepaalde Excel-versies zijn geëxporteerd. Los dit op door de juiste encoding in te stellen of“utf8-lossy”te gebruiken als het bestand inconsistente of kapotte tekens bevat. -
Problemen met scheidingstekens: Als je DataFrame wel laadt maar alle data in één kolom gepropt zit, heeft Polars het scheidingsteken niet herkend. Stel in dat geval expliciet de juiste delimiter in met het argument
separator, zoals puntkomma (;), tab (\t) of pipe (|). -
Onjuiste datatypes: Soms leidt Polars kolomtypes verkeerd af, bijvoorbeeld door numerieke ID’s als strings te lezen of op parsefouten te stuiten. Gebruik dan
schema_overridesom het datatype voor specifieke kolommen te bepalen. Als je de types voor alle kolommen wilt definiëren, gebruikschema. Je kunt ookinfer_schema_lengthverhogen, zodat Polars meer rijen bekijkt voordat het het schema afleidt. -
Geheugenproblemen bij grote bestanden: Als je Python-proces crasht bij het laden van een groot bestand, is je RAM op. Stap dan over van
read_csv()naarscan_csv()voor lazy loading om het geheugengebruik te verlagen en de performance te verbeteren. Je kunt ook minder kolommen laden of stream-uitvoering gebruiken om data in chunks te verwerken.
Conclusie
De functie read_csv() in Polars is eenvoudig in gebruik maar krachtig genoeg voor realistische taken. Naar mijn mening heeft Polars een duidelijk voordeel bij groeiende datasets.
Bekijk als volgende stap onze blog over de Polars GPU-engine om meer te leren over de verschillende toepassingen. Ben je klaar om praktisch aan de slag te gaan, volg dan onze Super Bowl Analytics with Polars code-along om echte analytische vragen op te lossen, berekeningen toe te passen en basis-ML-technieken te gebruiken voor sportanalytische problemen.
FAQs
Wat is het verschil tussen read_csv() en scan_csv() in Polars?
read_csv() laadt data meteen (eager) in het geheugen, terwijl scan_csv() luie uitvoering gebruikt en data pas verwerkt wanneer je .collect() aanroept.
Wanneer moet ik scan_csv() gebruiken in plaats van read_csv()?
Gebruik scan_csv() voor grote datasets of wanneer je transformaties aan elkaar rijgt, omdat het de uitvoering optimaliseert en het geheugengebruik vermindert.
Kan Polars alleen specifieke kolommen uit een CSV-bestand lezen?
Ja, gebruik de parameter columns=[...] in read_csv() of selecteer kolommen in een luie query met scan_csv().
Hoe ga ik om met missende waarden in Polars CSV-bestanden?
Polars behandelt lege waarden standaard als null, en je kunt aangepaste null-markers definiëren met null_values=.
Ondersteunt Polars gecomprimeerde CSV-bestanden?
Ja, het kan gecomprimeerde formaten zoals .gz en .zip lezen zonder handmatig uit te pakken.
