Python Polars 1.x Rehberi: Pandas'tan 10x Hızlı DataFrame İşlemleri (2026)
Polars 1.x ile pandas'tan 5-30x hızlı DataFrame işlemleri: lazy API, expression API, streaming engine ve pandas'tan geçiş örnekleri eşliğinde 2026 rehberi.
Polars, pandas'a alternatif olarak Rust dilinde yazılmış, Apache Arrow tabanlı yüksek performanslı bir DataFrame kütüphanesidir ve aynı veri işleme görevlerini pandas'a kıyasla genellikle 5 ila 30 kat daha hızlı tamamlar. Sürüm 1.x ile API stabil hale gelen Polars, lazy evaluation (tembel değerlendirme), expression API ve streaming engine özellikleriyle hem küçük not defteri analizlerinde hem de RAM'e sığmayan onlarca gigabaytlık veri setlerinde çalışabilir. Bu rehber, Polars'ı 2026 yılının en güncel sürümüyle adım adım gösterir.
Polars 1.x, Rust ve Apache Arrow üzerine kurulu olduğu için pandas'tan ortalama 5-30x daha hızlı çalışır ve aynı işlem için %50-80 daha az bellek tüketir.
Lazy API (pl.scan_csv, pl.scan_parquet) sorguyu yürütmeden önce optimize eder; predicate ve projection pushdown sayesinde diskten sadece gereken sütun ve satırlar okunur.
Expression API (pl.col, pl.when) vektörize işlemleri zincirlemeyi sağlar ve apply tabanlı Python döngüleri olmadan groupby/window işlemlerinde paralel yürütme sunar.
Streaming engine, belleğe sığmayan veri setlerini chunk'lar halinde işleyerek tek makinede 100+ GB CSV/Parquet dosyalarıyla analiz yapmayı mümkün kılar.
Pandas'tan geçiş çoğunlukla yöntem isimleri ve pl.col ifadeleriyle sınırlıdır; .to_pandas() ve pl.from_pandas() ile çift yönlü dönüştürme tek satırdır.
Polars'ı ilk kez 2023'ün ortasında, pandas'ta saatlerce süren bir groupby işini hızlandırmak için denemiştim; aynı sorgu 6 dakikadan 22 saniyeye düşünce kalıcı olarak iş akışıma girdi. Polars, Ritchie Vink tarafından başlatılan ve Rust dilinde yazılmış açık kaynak bir DataFrame kütüphanesidir. Bellek modeli olarak Apache Arrow kolonlu (columnar) formatı kullanır, bu sayede CPU önbelleğini verimli kullanır ve SIMD (Single Instruction Multiple Data) talimatlarıyla vektörize işlemler yapar. 2024'te 1.0 sürümüne ulaşan kütüphane, 2026 itibarıyla 1.20 üzerinde stabil bir sürüme sahip ve PyPI üzerinde ayda 25 milyondan fazla indirme alıyor.
Polars'ı sektörde öne çıkaran üç özellik var: çoklu çekirdek (multi-core) paralelliği varsayılan olarak açıktır, lazy evaluation sorguyu çalıştırmadan önce mantıksal bir optimize ediciden geçirir ve streaming engine RAM'den büyük veri setlerini işleyebilir. Pandas 3.0 da Apache Arrow desteğini genişletse de Polars'ın query optimizer'ı ve paralel yürütme motoru, özellikle 10 milyon satırın üzerindeki iş yüklerinde belirgin bir hız farkı yaratır. Polars'ın resmi sitesinde yayımlanan TPCH benchmark sonuçları, aynı sorgular için pandas'a kıyasla 3-50x arası hızlanma raporlar.
Eğer veri analitiği iş akışınızda zaten Python ile DuckDB kullanıyorsanız, Polars onu tamamlayıcı bir araç olarak düşünebilirsiniz: DuckDB SQL odaklı, Polars ise DataFrame odaklı API sunar ve ikisi de aynı Arrow bellek formatını paylaştığı için aralarında sıfır kopya (zero-copy) veri aktarımı mümkündür.
Polars 1.x kurulumu ve ilk DataFrame
Polars 1.x'i kurmak için Python 3.9 veya üzeri bir sürüm yeterlidir. Pip ile temel kurulum:
pip install polars
# Tüm opsiyonel özellikler (Parquet, Excel, S3, fsspec) ile:
pip install "polars[all]"
# Eski CPU'lar için (AVX2 olmayan):
pip install polars-lts-cpu
Kurulumu doğrulayalım ve ilk DataFrame'i oluşturalım:
Polars'ın çıktısı pandas'a benzer biçimde formatlıdır, fakat her sütunun veri tipi açıkça gösterilir. Bu, Apache Arrow'un sıkı tipli (strongly typed) yapısının doğal bir sonucudur ve şema sürüklenmesi (schema drift) hatalarını erken yakalamanıza yardımcı olur.
Bir CSV dosyasını okumak için iki yol vardır: hemen yürüten read_csv ve lazy scan_csv:
# Eager (anında yükle):
df = pl.read_csv("satislar.csv")
# Lazy (sorgu planı oluştur, .collect() ile çalıştır):
lf = pl.scan_csv("satislar.csv")
result = lf.filter(pl.col("tutar") > 100).select(["tarih", "tutar"]).collect()
Polars pandas'tan neden daha hızlı?
Polars'ın hız avantajı tek bir nedene değil, mimari kararların toplamına dayanır. İlk olarak, Polars Python'da değil Rust'ta yazılmıştır; bu, Python'un GIL (Global Interpreter Lock) kısıtlamasından bağımsız çalışan ve native CPU komutlarını doğrudan kullanan bir motor sağlar. Pandas ise NumPy üzerine kurulu ve birçok işlem GIL altında seri olarak yürütülür.
İkinci olarak, Polars varsayılan olarak çoklu çekirdek kullanır. Bir groupby veya join işlemi, makinenizdeki tüm CPU çekirdeklerine otomatik dağıtılır. Pandas'ta aynı paralellik için Dask, Modin veya Ray gibi ek kütüphanelere ihtiyaç vardır; pandas ile veri temizleme iş akışında bile sıklıkla tek çekirdekli kalırsınız.
Üçüncü olarak, lazy API bir query optimizer içerir. Filtreler kaynağa yakın itilir (predicate pushdown), sadece gereken sütunlar diskten okunur (projection pushdown), sabit ifadeler önceden hesaplanır (constant folding) ve common subexpression elimination uygulanır. Aşağıdaki tablo özet bir karşılaştırma sunar:
Özellik
Polars 1.x
Pandas 3.0
Yazıldığı dil
Rust
Python + Cython
Bellek modeli
Apache Arrow (kolonlu)
NumPy / opsiyonel Arrow
Paralellik
Çok çekirdekli (varsayılan)
Tek çekirdekli (varsayılan)
Lazy evaluation
Yerleşik (LazyFrame)
Yok
Query optimizer
Var (predicate/projection pushdown)
Yok
Bellek tüketimi (10M satır groupby)
~1.2 GB
~4.8 GB
Streaming engine
Var
Yok (Dask gerekir)
NULL davranışı
Açık (üç durumlu mantık)
NaN/NaT karışıklığı
Lazy evaluation nedir ve ne zaman kullanılır?
Lazy evaluation, Polars'ın işlemleri hemen yürütmek yerine bir LazyFrame üzerinde sembolik bir sorgu planı (logical plan) inşa etmesidir. .collect() çağrıldığında bu plan optimize edilir ve fiziksel olarak çalıştırılır. Bu, SQL veritabanlarındaki sorgu planlayıcılara benzer ve büyük dosyalarla çalışırken devasa hız ve bellek kazançları sağlar.
Pratik bir örnek: 50 sütunlu 100 milyon satırlık bir Parquet dosyasından sadece 3 sütunu, belirli bir filtreyle istiyorsunuz.
import polars as pl
# Lazy plan oluştur (henüz dosya okunmaz)
plan = (
pl.scan_parquet("buyuk_log.parquet")
.filter(pl.col("durum") == "hata")
.filter(pl.col("tarih") >= "2026-01-01")
.select(["tarih", "kullanici_id", "mesaj"])
.group_by("kullanici_id")
.agg(pl.len().alias("hata_sayisi"))
.sort("hata_sayisi", descending=True)
.head(20)
)
# Mantıksal ve fiziksel planı incele
print(plan.explain())
# Sorguyu çalıştır
sonuc = plan.collect()
print(sonuc)
Polars bu sorguyu çalıştırırken Parquet metadata'sını okur, sadece üç sütunu diskten getirir ve filtreyi mümkün olduğunca alt katmana iter. Eager API ile aynı işi yapmak isteseydiniz, önce 50 sütunlu tüm dosyayı belleğe yükler, sonra filtreler ve atardınız - bu hem yavaş hem de RAM açısından pahalı olurdu.
Expression API ile sütun işlemleri
Polars'ın en güçlü kavramı expression'lardır. Bir expression, "şu sütunu al, şunu yap, alias ata" şeklinde tanımlanan bağımsız bir hesaplama tarifidir. pl.col("x") * 2 bir expression'dır; tek başına çalışmaz, bir select, with_columns, filter veya group_by().agg() bağlamında değerlendirilir.
Expression'lar birbirleriyle zincirlenebilir, paralel olarak yürütülür ve apply tabanlı Python döngülerine kıyasla 50-100x daha hızlıdır. Pandas'taki df["x"].apply(lambda v: ...) deseni Polars'ta nadiren gerekir - neredeyse her dönüşüm için bir vektörize ifade vardır.
String ve tarih işlemleri, namespace'ler altında düzenlenmiştir:
Polars'ın group_by sözdizimi pandas'a benzer, ancak agregasyonlar expression olarak yazılır ve paralel yürütülür. Aynı dataframe içinde birden fazla agregasyonu tek bir agg bloğunda toplayabilirsiniz:
Join işlemleri için inner, left, outer, semi, anti ve cross türleri desteklenir. Pencere fonksiyonları over ile yazılır ve aynı satırlarda grup-bazlı hesaplama yapar:
Bu desen pandas'ta groupby().transform() ile elde edilen sonuca eşdeğerdir, ancak Polars'ta tüm over ifadeleri tek bir tarama içinde paralel hesaplanır. pandas DataFrame birleştirme rehberindeki kavramların çoğu Polars'a doğrudan taşınabilir.
Streaming engine ile büyük veri
Polars 1.x'in en dikkat çekici özelliklerinden biri, RAM'e sığmayan veri setlerini chunk'lar halinde işleyebilen streaming engine'dir. .collect(streaming=True) veya yeni API'de .collect(engine="streaming") kullanarak motor seçilir. Bu modda Polars veriyi parça parça okur, ara sonuçları diske dökmeden agrege eder ve nihai sonucu üretir.
Pratikte streaming, ETL boru hatlarında ve günlük log analizi gibi büyük tarama işlerinde 10 GB üzerindeki dosyalar için belleği sabit tutar; örneğin 80 GB Parquet'i 4 GB RAM'li bir konteynerde işleyebilirsiniz. Geçen yıl bir müşteri projesinde, pandas ile saatler süren bir gecelik ETL'yi streaming Polars'a taşıdığımızda 4 vCPU'lu bir worker'da süreyi 18 dakikaya çekmiştik (ve RAM kullanımı 32 GB'tan 5 GB'a düştü). Performans için verinizi mümkünse Parquet formatında ve mantıklı bir bölümleme (partitioning) düzeniyle saklayın.
Pandas'tan Polars'a nasıl geçilir?
Pandas kullanıcıları için Polars'a geçiş, sözdizimi farklılıklarına alışmaktan ibarettir. En sık karşılaşılan eşleşmeler:
df["col"] -> df["col"] aynıdır; ancak ifade olarak pl.col("col") tercih edilir.
df.apply(func, axis=1) -> mümkünse expression'lara çevirin; gerçekten gerekirse df.map_rows(func)
Mevcut pandas pipeline'ınızı tek seferde dönüştürmek zorunda değilsiniz. İkisi arasında köprü kurmak çok kolaydır:
import pandas as pd
import polars as pl
# Pandas DataFrame'i Polars'a aktar
pdf = pd.read_csv("girdi.csv")
df = pl.from_pandas(pdf)
# Polars ile agir isi yap
sonuc = (
df.lazy()
.filter(pl.col("durum") == "aktif")
.group_by("kategori")
.agg(pl.col("gelir").sum())
.collect()
)
# Eski koda geri ver
pdf_sonuc = sonuc.to_pandas()
Apache Arrow tabanlı dönüşüm sıfır kopya olduğu için, bu çift yönlü aktarım çok büyük dataframe'lerde bile milisaniyeler sürer. Pandas 3.0'ın PyArrow backend'i etkinleştirildiğinde performans farkı daha da küçülür, ancak Polars'ın query optimizer'ı ve paralel yürütmesi avantajını korur.
Production için en iyi uygulamalar
Polars'ı üretim iş yüklerinde kullanırken birkaç pratik kural önemli farkı yaratır:
Lazy API'yi varsayılan yapın. Tek satırlık keşif analizler dışında scan_* fonksiyonlarını kullanın ve sorguyu son anda .collect() ile çalıştırın. Optimizer büyük çoğunlukla sizden daha iyi karar verir.
Şemayı açıkça belirtin.pl.scan_csv(path, schema_overrides={"id": pl.Int64}) ile tip çıkarımını atlayın; bu hem hız kazandırır hem de schema drift hatalarını erkenden yakalar. Veri kalitesi için veri temizleme pratiklerinizi Polars'a taşıyın.
Parquet'i tercih edin. CSV yerine Parquet, hem dosya boyutunu küçültür hem de sütun bazlı okumayı mümkün kılar. Zaman bazlı bölümleme (year=2026/month=06/) ile predicate pushdown çok daha etkilidir.
String kategorilerini Categorical veya Enum yapın. Tekrar eden değerler için bu tipler bellek tüketimini %80'e kadar düşürür ve groupby/join hızlanır.
Streaming'i büyük tarama işlerinde kullanın. Tüm sorguyu RAM'de tutmak gerekmeyen analitik için engine="streaming" tercih edin.
Polars + DuckDB + Arrow üçlüsünü öğrenin. SQL gerektiren bölümler için DuckDB, DataFrame API için Polars, depolama için Parquet/Arrow - bu üçü 2026 modern veri yığını için son derece güçlü bir tabandır.
Kısa vadede hayır; pandas hâlâ ekosistemde en yaygın kullanılan kütüphane ve scikit-learn, statsmodels gibi araçlar pandas DataFrame'i doğal girdi olarak alıyor. Ancak büyük veri ve performans odaklı iş yüklerinde Polars hızla standart hâline geliyor; çoğu ekip pandas ve Polars'ı bir arada kullanıyor.
Polars 1.x'te tipik hız kazancı nedir?
İşlem türüne göre değişir. 1 milyon satırın altında genellikle 2-5x, 10 milyon satırda 10-20x, lazy + streaming kullanılan büyük taramalarda 30x üzerinde hızlanma raporlanıyor. Asıl kazanç bellek tüketiminde: aynı işlem için Polars genellikle pandas'ın %30-50 RAM'ini tüketir.
Polars scikit-learn ile birlikte çalışır mı?
Evet, ama scikit-learn pandas/NumPy bekler. Polars DataFrame'i modele vermeden önce .to_pandas() veya .to_numpy() çağırırsınız. Apache Arrow backend'i sayesinde bu dönüşüm çoğu zaman sıfır-kopya ve milisaniyeler düzeyindedir.
Lazy ve eager API arasındaki fark nedir?
Eager API (pl.read_csv, DataFrame) her işlemi anında çalıştırır; pandas mantığına yakındır. Lazy API (pl.scan_csv, LazyFrame) sorgu planı oluşturur, optimize eder ve .collect() çağrıldığında çalıştırır. Üretim iş yükleri için lazy neredeyse her zaman daha hızlı ve hafıza dostudur.
Polars Apache Spark'a alternatif olabilir mi?
Tek makine ölçeğinde (100 GB-1 TB arası) evet, hatta genellikle daha hızlı ve operasyonel olarak çok daha basittir. Ancak gerçek dağıtık iş yükleri (10+ TB, çok düğümlü kümeler) için Spark veya Ray gibi dağıtık motorlar hâlâ gereklidir. 2026'da pek çok ekip Spark işlerini tek makineli Polars boru hatlarına taşıyarak maliyetlerini ciddi oranda düşürdü.
Pandera 0.22 ile Pandas ve Polars DataFrame'leri için tip güvenli şema doğrulama: DataFrameModel, lazy validation, Polars LazyFrame entegrasyonu ve pytest ile üretim seviyesinde veri kontratları.
DuckDB ile Python'da SQL sorgularını Pandas'tan 5-10 kat daha hızlı çalıştırın. Kurulumdan üretim kullanımına, Parquet sorgularından performans ipuçlarına kadar pratik bir rehber.
Pandas 3.0 ve scikit-learn 1.8 ile Python'da aykırı değer tespiti: IQR, Z-skoru, Modified Z-Score, Isolation Forest, LOF ve DBSCAN yöntemlerini çalıştırılabilir kod örnekleriyle adım adım uygulayın.