Skip to the solution
MediumBackend12 min read

Polars vs pandas: when should you switch in 2025-26?

980 views

The problem

Question presented to candidate: "Our team does most of its data work in pandas. People keep saying we should move to Polars. What actually differs between the two, and how would you decide whether a given project should switch?"

What a strong answer should cover:

  • Engine: Polars is a Rust, multi-threaded, columnar (Apache Arrow memory) DataFrame library with an expression API and a lazy query optimizer; pandas is eager, mostly NumPy-backed, single-threaded for most operations
  • API model: Polars has no row index and no in-place mutation; pandas has the index (label alignment), a huge API and the widest ecosystem (scikit-learn, statsmodels, plotting, notebooks)
  • pandas 3.0 (January 2026) narrowed some gaps: Copy-on-Write is the only mode, text columns default to a str dtype, and pd.col expressions exist, but execution is still eager
  • When switching pays: large files (GBs), heavy group-by / join pipelines, ETL jobs where run time and memory cost money, new code without deep pandas dependencies; when it does not: small data, notebooks tied to pandas-only libraries, code that leans on the index
  • Migration strategy: switch at the pipeline boundary, convert with to_pandas() / from_pandas for the last step, benchmark on your real data, check Polars version changes (1.0 in July 2024; 2.0 makes streaming the default engine)

Clarifying questions expected:

  • How big is the data, and is the pain run time, memory, or code complexity?
  • Which downstream libraries consume the DataFrames, and do they require pandas?
  • Is this a new pipeline or a large existing codebase with tests?

Code / implementation expected: Optional β€” the same filter / group-by in both libraries, or a short argument with numbers from a benchmark on your own data.

  • polars
  • pandas
  • dataframe

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read Β· 9 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

PythonWhy a lazy, whole-query engine touches less data (toy model, runs in the page)
Pythonpandas 3.0 behaviours to weigh before switching: str dtype, Copy-on-Write, index alignment
# pandas 3.0 behaviours that matter when you compare it with Polars
# (needs: pip install "pandas>=3"; verified with pandas 3.0.5)
import warnings

import pandas as pd

print("pandas", pd.__version__.split(".")[0] + ".x")
df = pd.DataFrame({"city": ["Oslo", "Lima", "Oslo"], "sales": [10, 20, 30]})

# 1. Text columns are the new str dtype, not object
print("city dtype:", df["city"].dtype)

# 2. Copy-on-Write: chained assignment never writes to df
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter("always")
    df[df["city"] == "Oslo"]["sales"] = 0
print("warning:", [type(w.message).__name__ for w in caught])
print("after chained assignment:", df["sales"].tolist())

# A derived object is its own copy as far as writes go
sub = df[df["city"] == "Oslo"]
sub.loc[:, "sales"] = 1
col = df["sales"]
col.iloc[0] = 999
print("after writing to sub and col:", df["sales"].tolist())

# The one supported way to update in place: a single .loc call
df.loc[df["city"] == "Oslo", "sales"] = 0
print("after df.loc[...] = 0:", df["sales"].tolist())

# 3. The index: arithmetic aligns on labels, not positions
a = pd.Series([1, 2, 3], index=[0, 1, 2])
b = pd.Series([10, 20, 30], index=[1, 2, 3])
print("a + b:", (a + b).tolist())

# 4. Missing values in a NumPy int column upcast it to float
print("dtype with a None:", pd.Series([1, None, 3]).dtype)
print("nullable Int64:", pd.Series([1, None, 3], dtype="Int64").tolist())

# 5. pandas 3 also has pd.col expressions (Polars-like syntax, still eager)
print(df.assign(double=pd.col("sales") * 2)["double"].tolist())

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 56 of 139 in Python

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Python questions
Up nextMedium

What useful types does the collections module provide?

Continue