
Polars là gì? DataFrame library Python nhanh hơn Pandas
Polars DataFrame là thư viện xử lý dữ liệu tốc độ cao viết bằng Rust, thiết kế cho hiệu năng lớn nhất. Polars DataFrame vượt trội Pandas nhờ engine thực thi song song, quản lý bộ nhớ thông minh và API biểu thức (expression API) linh hoạt.
Trong thực tế, bạn gặp Polars trong các pipeline machine learning, phân tích log server, xử lý dataset chứng khoán hay báo cáo ETL trên data warehouse. Nếu Pandas mất hàng giờ để xử lý file lớn, Polars thường hoàn thành trong vài phút nhờ đa luồng và tối ưu tự động.
Tại sao Polars nhanh hơn Pandas?
Pandas chạy đơn luồng (single-threaded), giới hạn hiệu năng trên CPU đa nhân hiện nay. Polars giải quyết bài toán này bằng ba trụ cột:
- Đa luồng tự động: Polars tận dụng tất cả nhân CPU mà không cần cấu hình thêm.
- Zero-copy & Apache Arrow: Dữ liệu lưu ở định dạng cột (columnar), chia sẻ bộ nhớ giữa Rust và Python.
- Query optimizer: Engine tối ưu kế hoạch thực thi trước khi chạy — lọc sớm, gộp phép toán, loại cột không dùng.

Kiến trúc cốt lõi
DataFrame và Series
DataFrame là bảng dữ liệu 2 chiều; Series là cột đơn lẻ. Cả hai đều bất biến (immutable) — phép biến đổi trả về đối tượng mới, an toàn cho xử lý song song.
Expression API
Thay vì gán biến trung gian, bạn viết chuỗi biểu thức:
df.filter(pl.col("age") > 30)
.group_by("city")
.agg(pl.col("salary").mean())
Engine thấy toàn bộ pipeline, tối ưu hoá trước khi thực thi. Expression có thể tổ hợp lồng nhau (nested expressions) — ví dụ pl.col("x").filter(pl.col("y") > 0).mean() — giúp logic phức tạp gọn trong một dòng. So với Pandas df[df['y']>0]['x'].mean(), Polars không tạo bản sao trung gian.
LazyFrame — chế độ lười biếng
LazyFrame trì hoãn chạy cho đến khi gọi .collect(). Lợi ích:
- Tối ưu toàn cục (predicate pushdown, projection pushdown)
- Xử lý dữ liệu lớn hơn RAM (streaming)
- Kết hợp nhiều nguồn dữ liệu trước khi materialize
Predicate pushdown đẩy điều kiện lọc xuống nguồn dữ liệu (CSV, Parquet) — chỉ đọc row cần thiết. Projection pushdown chỉ nạp cột dùng đến. Streaming mode (.collect(streaming=True)) xử lý theo chunk, cho phép dataset lớn hơn bộ nhớ vật lý.
So sánh nhanh Polars vs Pandas
| Tiêu chí | Pandas | Polars |
|---|---|---|
| Ngôn ngữ cốt lõi | Python + C | Rust |
| Đa luồng | Không (cần modin/dask) | Tự động |
| Bộ nhớ | Row-major, copy nhiều | Columnar (Arrow), zero-copy |
| API | DataFrame method chaining | Expression API + SQL context |
| Streaming / out-of-core | Yếu | Mạnh (LazyFrame) |
| Học tập | Dễ, tài liệu nhiều | Khá dễ, cú pháp quen thuộc |
Cài đặt và bắt đầu
pip install polars
# hoặc với backend pyarrow
pip install "polars[pyarrow]"
Ví dụ đọc CSV 100 triệu dòng:
import polars as pl
# Eager mode
df = pl.read_csv("large_file.csv")
print(df.filter(pl.col("value") > 100).select("id", "name"))
# Lazy mode — khuyến nghị cho big data
lf = pl.scan_csv("large_file.csv")
result = lf.filter(pl.col("value") > 100).select("id", "name").collect()

Thao tác thường gặp
Lọc và chọn cột
df.filter((pl.col("age") > 25) & (pl.col("city") == "Hanoi"))
.select(["name", "salary", "department"])
Group by và aggregation
df.group_by("department").agg([
pl.col("salary").mean().alias("avg_salary"),
pl.col("salary").max().alias("max_salary"),
pl.count().alias("headcount")
])
Join đa luồng
# Hash join tự động song song
result = df_left.join(df_right, on="user_id", how="inner")
Window functions
df.with_columns([
pl.col("salary").rank().over("department").alias("rank_in_dept"),
pl.col("salary").mean().over("department").alias("dept_avg")
])
Tích hợp hệ sinh thái
- Apache Arrow / Parquet:
pl.read_parquet(),df.write_parquet()— định dạng cột chuẩn, nén tốt. - Pandas / NumPy:
df.to_pandas(),pl.from_pandas(pdf)— chuyển đổi zero-copy khi có pyarrow. - SQL:
pl.sql("SELECT * FROM df WHERE ...")— chạy SQL trực tiếp trên DataFrame. - DuckDB:
pl.read_database()— truy vấn DuckDB, trả về Polars DataFrame. - PyTorch / TensorFlow:
df.to_numpy(),df.to_torch()— pipeline ML liền mạch.
Tham khảo tài liệu chính thức: https://docs.pola.rs/
Mẹo hiệu năng và best practices
- Dùng LazyFrame mặc định:
pl.scan_csv()thay vìpl.read_csv()cho file lớn — tận dụng predicate/projection pushdown. - Chọn kiểu dữ liệu phù hợp:
pl.Int32,pl.Float32thay vì 64-bit khi giá trị cho phép — tiết kiệm 50% RAM. - Tránh
to_pandas()không cần thiết: Giữ Polars end-to-end; chỉ chuyển khi thư viện ML yêu cầu. - Partition Parquet: Ghi theo
partition_by=["year", "month"]— query sau chỉ đọc partition cần thiết. - Cấu hình thread pool:
pl.Config.set_tbl_rows(20)cho hiển thị,POLARS_MAX_THREADSenv var giới hạn nhân CPU (mặc định: tất cả).
Khi nào nên dùng Polars?
- Xử lý dữ liệu > 1GB trên máy đơn (laptop/server)
- Cần tốc độ đọc/ghi Parquet, CSV lớn
- Pipeline ETL/ELT sản xuất, yêu cầu ổn định và tái lập
- Kết hợp SQL + DataFrame trong cùng codebase
- Đội ngũ đã biết Pandas — chuyển đổi nhẹ nhàng
Hạn chế cần biết
- Cộng đồng nhỏ hơn Pandas, ít tutorial tiếng Việt
- Một số phép toán nâng cao (time-series resample phức tạp) chưa bằng Pandas
- Debug expression pipeline khó hơn method chaining quen thuộc
- Phiên bản < 1.0 — API có thể thay đổi (dù đã ổn định từ 0.19+)

Kết luận
Polars DataFrame mang hiệu năng Rust vào Python mà không đánh đổi trải nghiệm lập trình. Với Expression API, LazyFrame và đa luồng tự động, Polars là lựa chọn hợp lý cho xử lý dữ liệu lớn, pipeline production và thay thế Pandas khi hiệu năng trở thành bottleneck. Hãy thử pip install polars và chạy trên dataset thực tế — chênh lệch tốc độ thường từ 3x đến 50x.
Cập nhật 2024: Polars 1.0 đã phát hành, API ổn định, sẵn sàng production.
Tags: Framework, Git, Class
Category: Lập trình (ID: 107)
