데이터 엔지니어 · AI 엔지니어를 위한 핵심 요약
Polars는 Rust로 작성된 고성능 DataFrame 라이브러리입니다. Pandas와 유사한 API를 제공하면서도, Rust의 메모리 안전성과 병렬 처리 능력을 활용해 대규모 데이터 처리에 최적화되어 있습니다. 데이터 엔지니어와 데이터 사이언티스트가 실무에서 자주 마주하는 빅데이터 워크로드를 10~100배 빠르게 처리할 수 있습니다.
Polars의 3대 핵심 능력을 카드로 요약하면 다음과 같습니다:
Rust 기반의 쿼리 엔진으로, Pandas 대비 10~30배 빠른 속도. Arrow 메모리 포맷을 사용해 제로-카피 연산 지원.
연산을 즉시 실행하지 않고 쿼리 플랜을 최적화한 후 한 번에 실행. 메모리 효율성과 성능 극대화.
자동 멀티스레딩 지원. CPU 코어 수에 따라 병렬 처리로 대용량 데이터셋을 효율적으로 핸들링.
Pandas가 표준이지만, GB 단위 데이터에서 메모리 초과와 느린 속도가 문제입니다. Polars는 이러한 한계를 극복하며, Dask나 Vaex 같은 대안과 비교해도 우수합니다.
| 라이브러리 | 언어 | 속도 (상대적) | 메모리 효율 | Lazy Eval | 멀티스레드 |
|---|---|---|---|---|---|
| Pandas | Python | 1x | 낮음 | 없음 | 부분 |
| Dask | Python | 2~5x | 중간 (분산) | 있음 | 있음 (분산) |
| Polars | Rust/Python | 10~100x | 높음 | 있음 | 완전 |
| Modin | Python | 3~10x | 중간 | 부분 | 부분 |
결론: 실무에서 1GB+ 데이터셋 처리 시 Polars가 압도적. Pandas 코드 80% 호환으로 마이그레이션 용이.
Polars의 아키텍처는 Query Engine 중심입니다. Eager 모드(DataFrame)와 Lazy 모드(LazyFrame)를 지원하며, Streaming 모드로 초대용량 데이터 처리 가능.
위 다이어그램처럼 LazyFrame은 쿼리를 최적화(프레디케이트 푸시다운, 프로젝션 푸시다운)한 후 병렬 실행됩니다.
단계별로 시작해 보세요.
pip install polars[all]
CLI 도구(pv) 포함 설치.
import polars as pl
pl.Config.set_tbl_rows(100) # 테이블 출력 행 수
pl.Config.set_tbl_width_chars(120) # 테이블 너비
import polars as pl
import numpy as np
# DataFrame 생성
df = pl.DataFrame({
"a": [1, 2, 3, 4],
"b": ["w", "x", "y", "z"]
})
print(df)
# LazyFrame으로 변환
lf = df.lazy()
# 필터 + 그룹바이
result = lf.filter(pl.col("a") > 2).group_by("b").agg(pl.col("a").sum()).collect()
print(result)
pv read-csv data.csv --infer-schema-length 10000 | pv group-by category --agg sum(value) > output.csv
이제 대규모 CSV를 1분 만에 처리해 보세요!
| 설정 | 설명 | 기본값 | 예제 |
|---|---|---|---|
| pl.Config.set_tbl_rows | 테이블 출력 행 수 | 100 | pl.Config.set_tbl_rows(50) |
| pl.Config.set_tbl_cols | 테이블 출력 컬럼 수 | auto | pl.Config.set_tbl_cols(10) |
| pl.Config.set_tbl_width_chars | 테이블 너비 (chars) | 80 | pl.Config.set_tbl_width_chars(200) |
| pl.Config.set_fmt_str_lengths | 문자열 길이 포맷 | 50 | pl.Config.set_fmt_str_lengths(25) |
| pl.Config.set_float_precision | 부동소수점 정밀도 | 3 | pl.Config.set_float_precision(6) |
with pl.Config(tbl_rows=20): print(df)
lf.sink_parquet("output.parquet", compression="lz4")
팁: Join 전에 sort() 호출. df.join(other.sort("key"), on="key")
# 최적화된 조인
lf = df.lazy().sort("key").join(other.lazy().sort("key"), on="key")
팁: df.to_pandas(use_pyarrow_extension_array=True) 사용. PyArrow로 제로-카피.
pl.col("col").sum().alias("total").over("group")lf.sink_ipc("stream.arrow")로 메모리 절약.pl.threadpool_size() 확인 후 조정.