Skip to content

Polars - Fast DataFrame Library Cheatsheet

Polars - Fast DataFrame Library Cheatsheet

Polars is a high-performance DataFrame library written in Rust with Python, R, and Node bindings. It is multi-threaded by default, built on Apache Arrow columnar memory, and offers a lazy API with a query optimizer that reorders and prunes work before executing. On large datasets it is typically many times faster than pandas and uses less memory, while its expression API composes more cleanly. It has become the default recommendation for new data work in 2026.

Installation

MethodCommand
pippip install polars
uvuv add polars
With extraspip install "polars[all]" (excel, database, plotting)
Verifypython -c "import polars as pl; print(pl.__version__)"

Reading & Writing

OperationCode
CSVpl.read_csv("data.csv")
Parquetpl.read_parquet("data.parquet")
JSONpl.read_json("data.json")
Databasepl.read_database(query, connection)
Lazy CSVpl.scan_csv("data.csv") (deferred)
Lazy Parquetpl.scan_parquet("*.parquet")
Writedf.write_parquet("out.parquet")

Eager vs Lazy (the key idea)

import polars as pl

# Eager: executes immediately
df = pl.read_csv("sales.csv")
result = df.filter(pl.col("amount") > 100).group_by("region").agg(pl.col("amount").sum())

# Lazy: builds a plan, optimizes, then runs on .collect()
result = (
    pl.scan_csv("sales.csv")
      .filter(pl.col("amount") > 100)
      .group_by("region")
      .agg(pl.col("amount").sum())
      .collect()
)

Lazy mode lets the optimizer push filters down to the scan and read only needed columns — often a large speedup on big files. Prefer scan_* + .collect() for real workloads.

Expressions (the core API)

ExpressionDoes
pl.col("x")Reference a column
pl.col("x").sum()Aggregate
pl.col("x").alias("y")Rename output
pl.col("*")All columns
pl.lit(5)Literal value
pl.when(cond).then(a).otherwise(b)Conditional

Selecting & Filtering

TaskCode
Select columnsdf.select("a", "b")
Computed columndf.with_columns((pl.col("a") * 2).alias("a2"))
Filter rowsdf.filter(pl.col("a") > 10)
Multiple conditionsdf.filter((pl.col("a") > 10) & (pl.col("b") == "x"))
Head/taildf.head(10), df.tail(10)
Sortdf.sort("a", descending=True)
Uniquedf.unique(subset=["a"])

Aggregation & Grouping

(df.group_by("region")
   .agg(
       pl.col("amount").sum().alias("total"),
       pl.col("amount").mean().alias("avg"),
       pl.col("order_id").n_unique().alias("orders"),
   ))
AggregationExpression
Sum/mean/min/max.sum(), .mean(), .min(), .max()
Count.count(), .n_unique()
First/last.first(), .last()
Quantile.quantile(0.95)
List collect.implode()

Joins

TypeCode
Innera.join(b, on="id")
Lefta.join(b, on="id", how="left")
Outera.join(b, on="id", how="full")
Antia.join(b, on="id", how="anti")
Semia.join(b, on="id", how="semi")
As-of (time)a.join_asof(b, on="ts")

Strings, Dates, Lists

NamespaceExample
.strpl.col("s").str.to_uppercase(), .str.contains("x")
.dtpl.col("t").dt.year(), .dt.truncate("1h")
.listpl.col("l").list.len(), .list.first()
.castpl.col("a").cast(pl.Int64)

Interop

TargetCode
pandasdf.to_pandas() / pl.from_pandas(pdf)
Arrowdf.to_arrow()
NumPydf.to_numpy()
DuckDBQuery Polars frames directly from DuckDB

Polars vs pandas

AspectPolarspandas
EngineRust, multi-threadedPython/C, mostly single-threaded
MemoryArrow columnarNumPy-backed
Lazy optimizerYesNo
APIExpression-based, composableIndex-centric
EcosystemGrowing fastVast, mature

For SQL-first analytics over files, pair with DuckDB; pandas remains valuable for its ecosystem breadth.

Resources