Ha valaha ültél egy Pandas script előtt, ami egy egyszerű CSV beolvasáson 3 percig pörgött, vagy memóriahiány miatt dobott hibát egy közepes méretű adathalmaznál — nos, nem vagy egyedül. A Pandas évtizedeken át uralta a Python adatelemzést, de 2026-ra komolyan elgondolkodtató alternatíva érkezett: a Polars.
Ez az útmutató neked szól, ha kíváncsi vagy, hogyan állhatsz át Pandasról Polarsra a gyakorlatban. Nem csak elmélet lesz — konkrét szintaxis összehasonlítások, benchmark számok és működő kódpéldák várnak.
De mielőtt belevágnánk: a Polars nem egyszerűen egy „gyorsabb Pandas". Alapjaiban más megközelítést képvisel. Rust motor, Apache Arrow memóriaformátum, natív többszálúság, lusta kiértékelés — ezek nem buzzwordök, hanem valós előnyök, amiket tényleg érezni fogsz a munkád során.
Szóval, vágjunk bele.
Mi a Polars és miért gyorsabb a Pandasnál?
A Polars egy modern DataFrame könyvtár, amit Rust nyelven írtak, de Pythonból (meg más nyelvekből is) simán használható. A célja egyszerű: a lehető leggyorsabb táblázatos adatfeldolgozás, a modern hardver minden előnyének kihasználásával.
De miért pont gyorsabb? Nézzük meg a fő okokat.
Rust motor és Apache Arrow memóriaformátum
A Pandas a NumPy-ra épül és Python objektumokkal dolgozik. A Polars ezzel szemben a Rust teljesítményét használja, az adatokat pedig Apache Arrow oszlopos formátumban tárolja. Ez két dolgot jelent a gyakorlatban: rendkívül gyors memóriaelérést és zero-copy adatmegosztást más rendszerekkel.
Többszálú végrehajtás
Ez talán a legegyszerűbben megérthető különbség. A Pandas egyszálú — hiába van a gépedben 8 vagy 16 mag, a Pandas egyetlen egyet használ. Kicsit frusztráló, nem?
A Polars natívan többszálú: automatikusan szétosztja a munkát az összes elérhető CPU-mag között. Ez önmagában többszörös gyorsulást hoz, különösen nagyobb adathalmazoknál.
Lusta (lazy) vs mohó (eager) kiértékelés
A Pandas minden műveletet azonnal végrehajt — meghívod, lefut. A Polars viszont képes egy teljes végrehajtási tervet összeállítani és optimalizálni, mielőtt bármit is csinálna. Gondolj rá úgy, mint egy SQL query planner: összegyűjti a műveleteket, kidobja a feleslegeseket, és csak utána indítja el a számolást.
Erről később részletesen is lesz szó, mert ez tényleg a Polars egyik legizgalmasabb képessége.
Nincs index rendszer
Őszintén szólva, a Pandas index rendszere engem mindig kicsit zavart. Sosem voltam biztos benne, hogy mikor kell resetelni, mikor nem, és mi történik, ha elrontom.
A Polars egyszerűen nem használ indexet. Sorok és oszlopok — ennyi. Nincs rejtett index, ami váratlan viselkedést okozhatna.
Null kezelés
Klasszikus Pandas-fájdalom: van egy integer oszlopod, beteszel egy hiányzó értéket, és hirtelen az egész float-tá válik. Ez azért van, mert a Pandas NaN-t (Not a Number) használ, ami egy float típusú érték.
A Polars null értékekkel dolgozik, és megőrzi az eredeti adattípusokat. Kis dolog, de rengeteg fejfájást megspórol.
Teljesítmény-összehasonlítás konkrét számokkal
A benchmark teszteket egy 1 GB méretű CSV fájlon végeztük:
- CSV beolvasás: Polars 5-10x gyorsabb — a többszálú parser és az Arrow formátum együttes hatása.
- GroupBy művelet: Polars átlagosan 8x gyorsabb, mert párhuzamosan dolgozza fel a csoportokat.
- Join: Akár 13,75x gyorsabb nagy adathalmazoknál. Ez nem elírás.
- Memóriahasználat: 1 GB-os CSV-nél a Polars 179 MB-ot használ, a Pandas 1,4 GB-ot. Közel 8x-os különbség.
Ezek a számok nem mellébeszélés. Ha a teljesítmény és memóriahatékonyság fontos (és mikor nem az?), a Polars egyszerűen más kategória.
Telepítés és első lépések
A telepítés szerencsére nem tart tovább pár másodpercnél:
pip install polars
Ha mindent akarsz (Excel, Parquet, adatbázis-támogatás, időzóna kezelés), akkor:
pip install "polars[all]"
Nézzünk egy egyszerű DataFrame-létrehozást mindkét könyvtárral, hogy lássuk a hasonlóságokat és különbségeket.
Pandas megközelítés
import pandas as pd
df_pandas = pd.DataFrame({
"nev": ["Anna", "Béla", "Csaba", "Diána"],
"kor": [28, 35, 42, 31],
"varos": ["Budapest", "Debrecen", "Szeged", "Pécs"],
"fizetes": [750000, 620000, 580000, 690000]
})
print(df_pandas)
print(df_pandas.dtypes)
Polars megközelítés
import polars as pl
df_polars = pl.DataFrame({
"nev": ["Anna", "Béla", "Csaba", "Diána"],
"kor": [28, 35, 42, 31],
"varos": ["Budapest", "Debrecen", "Szeged", "Pécs"],
"fizetes": [750000, 620000, 580000, 690000]
})
print(df_polars)
print(df_polars.schema)
Ami rögtön feltűnik: a Polars kimenete szebben formázott, és a schema tulajdonság pontosan megmutatja az oszlopok típusait. Az alap DataFrame-létrehozás viszont szinte teljesen megegyezik — a valódi eltérések a műveleteknél jönnek elő.
Szintaxis összehasonlítás: Pandas vs Polars
Na, ez az a rész, amire a legtöbben kíváncsiak vagytok. Az átálláshoz ugyanis az kell, hogy tudd: amit Pandasban így csináltál, azt Polarsban hogyan kell. Íme a leggyakoribb műveletek egymás mellett.
CSV beolvasás
# Pandas
df = pd.read_csv("adat.csv")
# Polars (eager - azonnali beolvasás)
df = pl.read_csv("adat.csv")
# Polars (lazy - lusta beolvasás, ajánlott nagy fájloknál)
lf = pl.scan_csv("adat.csv")
Szűrés (filtering)
# Pandas
df_pandas[df_pandas["kor"] > 30]
df_pandas.query("kor > 30 and varos == 'Budapest'")
df_pandas.loc[df_pandas["kor"] > 30, ["nev", "kor"]]
# Polars
df_polars.filter(pl.col("kor") > 30)
df_polars.filter(
(pl.col("kor") > 30) & (pl.col("varos") == "Budapest")
)
Oszlop kiválasztás
# Pandas
df_pandas[["nev", "fizetes"]]
df_pandas.nev
# Polars
df_polars.select("nev", "fizetes")
df_polars.select(pl.col("nev", "fizetes"))
df_polars.select(pl.col(pl.Utf8)) # összes string oszlop
Csoportosítás (groupby)
# Pandas
df_pandas.groupby("varos").agg({"fizetes": ["mean", "count"]})
# Polars
df_polars.group_by("varos").agg(
pl.col("fizetes").mean().alias("atlag_fizetes"),
pl.col("fizetes").count().alias("letszam")
)
Figyeld meg, hogy a Polars szintaxis kicsit bőbeszédűbb, de sokkal egyértelműbb. Nem kell találgatni, melyik aggregáció melyik oszlopra vonatkozik.
Hiányzó értékek kezelése
# Pandas
df_pandas.fillna(0)
df_pandas.dropna()
df_pandas["kor"].isna()
# Polars
df_polars.fill_null(0)
df_polars.drop_nulls()
df_polars.select(pl.col("kor").is_null())
Join / Merge
# Pandas
pd.merge(df1, df2, on="azonosito", how="left")
# Polars
df1.join(df2, on="azonosito", how="left")
Apply kiváltása kifejezésekkel
Ez egy fontos rész. A Pandas apply() függvénye kényelmes, de lassú, mert soronként Python-kódot futtat. A Polarsban van ennél jobb megoldás:
# Pandas - lassú apply
df_pandas["kategoria"] = df_pandas["fizetes"].apply(
lambda x: "magas" if x > 700000 else "alacsony"
)
# Polars - gyors, vektorizált kifejezés
df_polars = df_polars.with_columns(
pl.when(pl.col("fizetes") > 700000)
.then(pl.lit("magas"))
.otherwise(pl.lit("alacsony"))
.alias("kategoria")
)
A lényeg: Polarsban pl.col() kifejezésekkel dolgozunk, az apply()-t pedig lehetőleg kerüljük. A when/then/otherwise szerkezet a feltételes logika barátja.
Lusta kiértékelés — a Polars titkos fegyvere
Ha egyetlen dolgot kellene kiemelnem, ami miatt a Polars igazán különleges, az a lusta kiértékelés (lazy evaluation) lenne. Ez az a pont, ahol a Polars nemcsak gyorsabb, hanem okosabb is, mint a Pandas.
A LazyFrame koncepció
Kétféle DataFrame van a Polarsban: a sima DataFrame (eager, azonnali) és a LazyFrame (lusta, halasztott). A LazyFrame nem tartalmaz tényleges adatokat. Csak egy végrehajtási tervet ír le — mint egy recept, amit még nem kezdtél el főzni.
A tényleges számítás a .collect() híváskor történik meg.
import polars as pl
# LazyFrame létrehozása scan_csv-vel (nem olvassa be azonnal a fájlt!)
lf = pl.scan_csv("nagy_adat.csv")
# Műveletek láncolása - semmi sem fut le még
eredmeny = (
lf
.filter(pl.col("ev") >= 2024)
.filter(pl.col("osszeg") > 100000)
.group_by("kategoria")
.agg(
pl.col("osszeg").sum().alias("teljes_osszeg"),
pl.col("osszeg").mean().alias("atlag_osszeg"),
pl.len().alias("tranzakciok_szama")
)
.sort("teljes_osszeg", descending=True)
.head(10)
)
# A végrehajtási terv megtekintése
print(eredmeny.explain())
# Tényleges végrehajtás
df_eredmeny = eredmeny.collect()
print(df_eredmeny)
Automatikus lekérdezés-optimalizálás
Miért jó ez? Mert a Polars lusta motorja a háttérben komoly optimalizálást végez:
- Predicate pushdown: A szűréseket a lehető legkorábbi pontra tolja. Ha egy CSV-ből csak a 2024 utáni sorokat kéred, már olvasás közben szűr — nem tölti be az egészet, aztán dobja ki a felesleget.
- Projection pushdown: Csak azokat az oszlopokat olvassa be, amikre tényleg szükséged van. 100 oszlopból 3-at használsz? A másik 97-et meg sem nyitja.
- Közös részkifejezések eliminálása: Ha ugyanazt a számítást többször is használod, csak egyszer hajtja végre.
Ez kb. olyan, mintha lenne egy nagyon okos asszisztensed, aki mielőtt nekiállna egy feladatnak, először végigolvassa az egészet, és kitalálja a leghatékonyabb sorrendet.
Streaming mód — memóriánál nagyobb adatok
Mi van, ha az adathalmaz egyszerűen nem fér a memóriába? A Polars streaming módja darabokban (batch-ekben) dolgozza fel az adatokat:
# Streaming végrehajtás memóriánál nagyobb adatokra
eredmeny = (
pl.scan_csv("hatalmas_fajl.csv")
.filter(pl.col("statusz") == "aktiv")
.group_by("regio")
.agg(pl.col("bevetel").sum())
.collect(streaming=True) # darabokban dolgozza fel
)
Ezzel akár több tíz GB-os fájlokat is kezelhetsz néhány száz MB memóriával. Próbáld meg ezt Pandasszal.
Gyakorlati migrációs példa: ETL pipeline
Elég volt az elméletből — nézzünk egy valós ETL (Extract, Transform, Load) pipeline-t. A feladat: betöltünk egy értékesítési CSV-t, megtisztítjuk, csoportosítjuk, összekapcsoljuk egy termékadatbázissal, majd Parquet-ba mentjük.
Pandas verzió
import pandas as pd
import time
start = time.time()
# 1. Betöltés
ertekesites = pd.read_csv("ertekesites.csv")
termekek = pd.read_csv("termekek.csv")
# 2. Tisztítás
ertekesites = ertekesites.dropna(subset=["termek_id", "osszeg"])
ertekesites = ertekesites[ertekesites["osszeg"] > 0]
ertekesites["datum"] = pd.to_datetime(ertekesites["datum"])
ertekesites["ev"] = ertekesites["datum"].dt.year
ertekesites["honap"] = ertekesites["datum"].dt.month
# 3. Aggregáció
havi_osszesites = (
ertekesites
.groupby(["termek_id", "ev", "honap"])
.agg(
teljes_osszeg=("osszeg", "sum"),
tranzakciok=("osszeg", "count"),
atlag_osszeg=("osszeg", "mean")
)
.reset_index()
)
# 4. Join termékadatokkal
eredmeny = pd.merge(
havi_osszesites,
termekek[["termek_id", "nev", "kategoria"]],
on="termek_id",
how="left"
)
# 5. Mentés
eredmeny.to_parquet("havi_jelentes.parquet", index=False)
print(f"Pandas idő: {time.time() - start:.2f} mp")
Polars verzió
import polars as pl
import time
start = time.time()
# 1-5. Teljes pipeline lusta kiértékeléssel
eredmeny = (
pl.scan_csv("ertekesites.csv")
# 2. Tisztítás
.drop_nulls(subset=["termek_id", "osszeg"])
.filter(pl.col("osszeg") > 0)
.with_columns(
pl.col("datum").str.to_datetime(),
)
.with_columns(
pl.col("datum").dt.year().alias("ev"),
pl.col("datum").dt.month().alias("honap"),
)
# 3. Aggregáció
.group_by("termek_id", "ev", "honap")
.agg(
pl.col("osszeg").sum().alias("teljes_osszeg"),
pl.col("osszeg").count().alias("tranzakciok"),
pl.col("osszeg").mean().alias("atlag_osszeg"),
)
# 4. Join
.join(
pl.scan_csv("termekek.csv").select("termek_id", "nev", "kategoria"),
on="termek_id",
how="left",
)
# 5. Összegyűjtés és mentés
.collect()
)
eredmeny.write_parquet("havi_jelentes.parquet")
print(f"Polars idő: {time.time() - start:.2f} mp")
A Polars verzió jellemzően 5-10x gyorsabb, de ami legalább ennyire fontos: olvashatóbb is. Az egész feldolgozási logikát egyetlen láncolható pipeline-ként írod le. A lusta kiértékelés pedig a háttérben automatikusan optimalizál — a termekek.csv-ből például csak a szükséges három oszlopot olvassa be (projection pushdown).
Mikor érdemes Polarsra váltani?
Fontos tisztázni: a Polars nem minden helyzetben a legjobb választás. (Igen, ezt mondom egy Polars-migrációs cikkben.) Íme egy őszinte útmutató.
Válaszd a Polarst, ha:
- Az adataid meghaladják az 1 GB-ot — itt a teljesítménykülönbség már drámai és nem lehet figyelmen kívül hagyni.
- Produkciós ETL pipeline-okat építesz — kiszámíthatóbb memóriahasználat, jobb teljesítmény.
- Sebesség kritikus — valós idejű adatfeldolgozás, API-k mögötti transzformációk.
- A memória szűk keresztmetszet — a streaming mód és a lusta kiértékelés komoly segítség.
- Többszálú feldolgozásra van szükséged — a Polars automatikusan kihasználja az összes CPU-magot.
Maradj a Pandasnál, ha:
- Kis adathalmazokkal dolgozol (pár MB) — a teljesítménykülönbség elhanyagolható, nem éri meg a váltás.
- Intenzíven használod az ML ökoszisztémát — a scikit-learn, statsmodels és társaik még mindig elsősorban Pandas DataFrame-eket várnak.
- A csapat nem ismeri a Polarst — a tanulási görbe és az átállás költsége kis projekteknél nem mindig éri meg.
- Interaktív adatelemzést végzel Jupyter notebookban — a Pandas integrációja és közösségi támogatása itt még erősebb.
Hibrid megközelítés
Ami szerintem a legpraktikusabb 2026-ban: a hibrid stratégia. Sokan csinálják úgy (és én is ezt javaslom), hogy a munkájuk nagyjából 70%-ában Pandast használnak feltárásra és prototipizálásra, a maradékban pedig — ahol a teljesítmény tényleg számít — Polarsra váltanak.
A konverzió a két könyvtár között triviális:
# Pandas DataFrame -> Polars DataFrame
df_polars = pl.from_pandas(df_pandas)
# Polars DataFrame -> Pandas DataFrame
df_pandas = df_polars.to_pandas()
Gyakori buktatók és tippek
Ha Pandasról jössz, van pár dolog, ami meg fog lepni. Jobb, ha előre felkészülsz rájuk.
1. A sorok sorrendje nem garantált
Bizonyos műveletek (pl. group_by) után a Polars nem garantálja a sorok eredeti sorrendjét. Ez a teljesítmény érdekében van így. Ha fontos a sorrend, mindig használj explicit .sort() hívást. Ez elsőre furcsa, de hamar megszokod.
2. Nincs .loc és .iloc
A Pandasból megszokott .loc és .iloc indexelés nem létezik Polarsban. Helyette .filter() és .select() a barátaid:
# Pandas
df_pandas.iloc[0:5]
df_pandas.loc[df_pandas["kor"] > 30, "nev"]
# Polars
df_polars.head(5) # vagy: df_polars.slice(0, 5)
df_polars.filter(pl.col("kor") > 30).select("nev")
3. Vége a SettingWithCopyWarning-nek
Ez sokaknak kedves hír lesz. A Pandas egyik leghírhedtebb figyelmeztetése a SettingWithCopyWarning — Polarsban egyszerűen nem létezik. A DataFrame-ek alapértelmezetten nem módosíthatók (immutable), minden művelet új DataFrame-et ad vissza. Tiszta, kiszámítható viselkedés.
4. Ne írj „Pandas-stílusú" Polars kódot
Ez az egyik leggyakoribb hiba. Sokan megpróbálják a Pandas logikáját egy az egyben átültetni Polarsba. Általában nem jó ötlet:
# ROSSZ - Pandas-stílusú gondolkodás Polarsban
for i in range(len(df_polars)):
ertek = df_polars.row(i)[0] # lassú, soronkénti iteráció
# JÓ - Polars-natív kifejezés
eredmeny = df_polars.select(
pl.col("oszlop").map_elements(lambda x: x * 2, return_dtype=pl.Int64)
)
# MÉG JOBB - teljesen vektorizált
eredmeny = df_polars.with_columns(
(pl.col("oszlop") * 2).alias("dupla_oszlop")
)
5. A kifejezés-rendszer a Polars szíve
A pl.col(), pl.when(), pl.lit() — ez a Polars lelke. Minden műveletet lehetőleg ezekkel a kifejezésekkel végezz, mert ezek fordulnak le hatékony Rust kódra, és ezek párhuzamosulnak a legjobban. A map_elements()-t kerüld, amennyire csak tudod — az visszaesik Python-szintre, és elveszíted a Polars összes előnyét.
Gyakran ismételt kérdések
A Polars teljesen leváltja a Pandast 2026-ban?
Röviden: nem. A Pandas továbbra is a legelterjedtebb DataFrame könyvtár Pythonban, és ez nem fog egyik napról a másikra megváltozni. Az ökoszisztémája hatalmas — ML könyvtárak, oktatóanyagok, Stack Overflow válaszok ezrei. A Polars viszont egyre nagyobb teret nyer, különösen produkciós környezetben. A legtöbb profi adatmérnök 2026-ban mindkettőt ismeri és használja, a feladattól függően.
Mennyivel gyorsabb a Polars a Pandasnál?
A feladattól és adatmérettől függ, de az általános számok: 5-10x gyorsabb CSV-beolvasásnál, 8x gyorsabb csoportosított aggregációknál, és akár 13,75x gyorsabb join műveleteknél. A memóriahasználatban a különbség még szembetűnőbb — akár 8x kevesebb memória. Kis adathalmazoknál (pár MB) viszont a különbség minimális.
Használhatok Polarst scikit-learn-nel?
Igen, bár némi konverzióra szükség lehet. A df_polars.to_pandas() vagy df_polars.to_numpy() hívással könnyen átadhatod az adatokat. Jó hír, hogy a scikit-learn 1.4-es verziójától egyre jobb a Polars-támogatás — a set_output(transform="polars") beállítással közvetlenül Polars kimenetet is kérhetsz.
Kell-e Rustot tudnom a Polars használatához?
Egyáltalán nem. A Polars Python API-ja teljes körű, és soha nem kell Rust kódot írnod. A Rust csak a belső motor nyelve — neked erről semmit sem kell tudnod. A legtöbb Pandas-felhasználó néhány nap alatt magabiztosan kezeli a Polarst.
Hogyan kezeli a Polars a memóriánál nagyobb adathalmazokat?
Két fő mechanizmussal. Az első a lusta kiértékelés: a scan_csv() és hasonló scan_* függvények nem töltik be az egész fájlt, csak a szükséges adatokat olvassák be. A második a streaming mód (.collect(streaming=True)), ami darabokban dolgozza fel az adatokat. Így akár több tíz GB-os fájlokat is kezelhetsz néhány száz MB memóriával. Ez a Polars egyik legnagyobb előnye a Pandasszal szemben, ami mindig mindent betölt a memóriába.