Polars vs Pandas:2026年に使うべきDataFrameライブラリはどっち?
Updated on
Pythonでデータを扱っているなら、Pandasでほぼ確実に壁にぶつかった経験があるはずです。2GBのCSVを読み込んだ途端にマシンが固まる。5,000万行のGroupBy集計が、秒で終わると思ったのに分単位でかかる。パイプラインを並列化しようとして、Pandasが本質的にシングルスレッドである現実に直面する。Pythonにおける表形式データ分析を世に広めたライブラリは、現代のチームが日常的に扱うデータ規模を前提には設計されていませんでした。
これは些細な不便ではありません。遅いデータパイプラインはチーム全体を止めます。データサイエンティストは分析を反復する代わりにノートブックの終了待ちをすることになります。エンジニアは回避策を作る――データをチャンクに分ける、ラップトップで済むはずのジョブのためにSparkクラスタを立てる、あるいはPythonをSQLに書き換える。コストは、失われた作業時間、洞察の遅延、そしてデータそのものより速く膨らむインフラ費用として現れます。
Polarsは、最有力の代替として台頭しました。Rustでゼロから作られ、Apache Arrowをメモリ基盤に持つPolarsは、Pandasより5〜30倍速く処理し、しかもメモリ使用量はその一部で済むことが多いです。遅延評価、自動マルチスレッド実行、そしてコードを書き換えて効率的に走らせるクエリオプティマイザを備えています。一方でPandasも停滞しているわけではありません。2.xではArrow-backed dtypesが導入され、性能改善も進みました。それでもPandasの周辺エコシステムは依然として無類です。
この記事では、2026年時点でのPolarsとPandasを、直接的かつ実務目線で比較します。構文の違い、性能ベンチマーク、メモリ使用量、エコシステム互換性、そしてどちらを選ぶべきかの明確な指針を提供します。
Pandasとは?
Pandasは、Pythonにおける基盤的なデータ操作ライブラリです。2008年にWes McKinneyによって公開され、DataFrameという抽象をPythonにもたらし、データのクリーニング、変換、分析の標準ツールになりました。2026年時点でPandasはGitHub starsが45,000以上あり、ほぼあらゆるデータサイエンスプロジェクトで依存関係としてインストールされています。
Pandasの主な特性:
- 即時評価(Eager evaluation):呼び出した操作はその場で実行される
- NumPyベースの配列:従来は内部でNumPy配列を使用(2.0以降はArrow backendも利用可能)
- シングルスレッド実行:デフォルトでは1つのCPUコアで実行
- 成熟したAPI:充実したドキュメント、膨大なチュートリアル、scikit-learn / matplotlib / seabornなどPyDataエコシステム全体との深い統合
- ミュータブルなDataFrame:in-place変更をサポート
Pandas 2.xでは、任意でPyArrow-backed dtypesを導入し、文字列中心データのメモリ効率を改善しつつ、Arrowベースの他ツールとの相互運用性も向上しました。しかし、実行モデルの中核は依然として「即時評価+シングルスレッド」です。
Polarsとは?
PolarsはRustで書かれたDataFrameライブラリで、2020年にRitchie Vinkによって作られました。Apache Arrowをインメモリの列指向フォーマットとして採用し、Arrow互換ツール間でのゼロコピー共有を可能にします。Polarsは、Pandasアーキテクチャに内在する性能制約を解決するためにゼロから設計されています。
Polarsの主な特性:
- 遅延評価と即時評価の両方:両モードをサポート。遅延モードでは実行前にクエリ最適化が可能
- Apache Arrowのメモリモデル:列指向ストレージでキャッシュ効率が高い
- 自動マルチスレッド:ユーザー操作なしで利用可能なCPUコアに自動で並列化
- クエリオプティマイザ:実行計画を再構成・最適化(predicate pushdown、projection pushdown、join reordering)
- ストリーミング実行:RAMより大きいデータセットも処理可能
- イミュータブルなDataFrame:全操作は新しいDataFrameを返し、in-place変更はしない
- GPU support:インメモリ処理向けに任意でNVIDIA GPUアクセラレーション
PolarsはPython APIとネイティブのRust APIを提供します。Python APIはPandasユーザーに馴染みやすい一方、メソッドチェーンとexpressionベースの構文を採用しており、オプティマイザが効果的に働けるようになっています。
Polars vs Pandas:完全比較表
| Feature | Pandas | Polars |
|---|---|---|
| Language | Python (C/Cython internals) | Rust (Python bindings via PyO3) |
| Memory Backend | NumPy (Arrow optional in 2.x) | Apache Arrow (native) |
| Execution Model | Eager only | Eager and Lazy |
| Multi-threading | Single-threaded | Automatic parallel execution |
| Query Optimizer | No | Yes (predicate pushdown, projection pushdown) |
| Streaming (out-of-core) | No (manual chunking required) | Yes (built-in streaming engine) |
| Memory Efficiency | Higher memory usage, copies on many operations | 30-60% less memory on typical workloads |
| CSV Read Speed | Baseline | 3-5x faster |
| GroupBy Speed | Baseline | 5-10x faster |
| Sort Speed | Baseline | 10-20x faster |
| Join Speed | Baseline | 3-8x faster |
| Index Support | Row index (central to API) | No index (uses columns for all operations) |
| Missing Values | NaN (float-based) and pd.NA | null (Arrow native, distinct from NaN) |
| String Handling | Object dtype (slow) or Arrow strings | Arrow strings (fast, memory-efficient) |
| GPU Support | No native support | NVIDIA GPU acceleration (optional) |
| Ecosystem Integration | Deep (scikit-learn, matplotlib, seaborn, etc.) | Growing (DuckDB, Arrow ecosystem, converters) |
| Learning Curve | Moderate (extensive resources) | Moderate (familiar concepts, new syntax) |
| Maturity | 17+ years, extremely stable | 5+ years, rapidly maturing |
| Package Size | Lightweight | Larger binary (includes Rust runtime) |
構文比較:同じ処理を並べたコード例
実務上の違いを理解する最良の方法は、同じ操作を両ライブラリで書いてみることです。以下の例は、よくあるデータ作業を示します。
CSVファイルの読み込み
Pandas:
import pandas as pd
df = pd.read_csv("sales_data.csv")
print(df.head())Polars:
import polars as pl
df = pl.read_csv("sales_data.csv")
print(df.head())単純なCSV読み込みでは構文はほぼ同じです。Polarsは列を並列に読み込み、Arrowのメモリフォーマットを直接使うため高速になります。1GBのCSVなら、Polarsは通常2秒未満で終わる一方、Pandasは8〜10秒かかることが一般的です。
Parquetファイルの読み込み
Pandas:
df = pd.read_parquet("sales_data.parquet")Polars (lazy -- only reads needed columns):
df = pl.scan_parquet("sales_data.parquet")
# No data loaded yet -- just a query plan
result = df.select("product", "revenue", "date").collect()ここがPolarsの真価です。scan_parquet はlazy frameを作り、実際に使う列と行だけを読み込みます。Parquetに100列あって3列しか使わないなら、Polarsは残り97列を丸ごとスキップします。Pandasは100列すべてをメモリに読み込みます。
行のフィルタリング
Pandas:
# Filter rows where revenue > 1000 and region is "North"
filtered = df[(df["revenue"] > 1000) & (df["region"] == "North")]Polars:
# Filter rows where revenue > 1000 and region is "North"
filtered = df.filter(
(pl.col("revenue") > 1000) & (pl.col("region") == "North")
)Polarsはブラケットのインデクシングではなく pl.col() のexpressionシステムを使います。これは単なる書き方の好みではなく、expressionにすることでクエリオプティマイザがフィルタをデータソース側へ押し込み、評価を並列化できるようになります。
GroupBy集計
Pandas:
result = df.groupby("category").agg(
total_revenue=("revenue", "sum"),
avg_price=("price", "mean"),
order_count=("order_id", "count")
)Polars:
result = df.group_by("category").agg(
total_revenue=pl.col("revenue").sum(),
avg_price=pl.col("price").mean(),
order_count=pl.col("order_id").count()
)どちらもnamed aggregationに対応しています。Polarsのexpression構文のほうが明示的で合成しやすい設計です。たとえば pl.col("revenue").filter(pl.col("status") == "completed").sum() のように、集計内で操作を簡単にチェーンできます。Pandasで同じことをやるには、より回りくどいコードになりがちです。
2つのDataFrameの結合(Join)
Pandas:
merged = pd.merge(
orders, customers,
left_on="customer_id",
right_on="id",
how="left"
)Polars:
merged = orders.join(
customers,
left_on="customer_id",
right_on="id",
how="left"
)joinの構文は両者で似ています。Polarsは複数スレッドでハッシュとプローブを並列に行え、lazy modeでは最適な実行のためにjoin順序を変更できるため、高速に動作します。
列の追加と変換
Pandas:
df["profit_margin"] = (df["revenue"] - df["cost"]) / df["revenue"] * 100
df["year"] = pd.to_datetime(df["date"]).dt.year
df["category_upper"] = df["category"].str.upper()Polars:
df = df.with_columns(
profit_margin=((pl.col("revenue") - pl.col("cost")) / pl.col("revenue") * 100),
year=pl.col("date").cast(pl.Date).dt.year(),
category_upper=pl.col("category").str.to_uppercase()
)Polarsは with_columns() で複数列の追加・変換を一括で行います。上の3つの変換は並列に実行されます。Pandasでは各行が順に実行され、中間コピーが作られます。
操作のチェーン(フルパイプライン)
Pandas:
result = (
df[df["status"] == "completed"]
.groupby("product_category")
.agg(total_revenue=("revenue", "sum"))
.sort_values("total_revenue", ascending=False)
.head(10)
)Polars (lazy mode):
result = (
df.lazy()
.filter(pl.col("status") == "completed")
.group_by("product_category")
.agg(total_revenue=pl.col("revenue").sum())
.sort("total_revenue", descending=True)
.head(10)
.collect()
)Polarsのlazyパイプラインは実行計画を構築し、実行前に最適化します。オプティマイザは、scanの前にfilterを押し込む、必要列だけを投影する、効率の良い順序に並べ替えるなどを自動で行います。.lazy() で開始し、最後に .collect() を呼ぶだけで、これらの最適化が得られます。
性能ベンチマーク
実務ベンチマークでは、PolarsがPandasを大きく上回る結果が一貫して見られます。以下は2025年の公開ベンチマークとPolarsのPDS-H benchmark suiteに基づく数値です。
CSV読み込み(1 GBファイル、約1,000万行)
| Library | Time | Memory Used |
|---|---|---|
| Pandas | 8.2s | 1.4 GB |
| Polars | 1.6s | 0.18 GB |
PolarsはCSVを5倍速く読み込み、メモリ使用量は約87%少なくなります。これは、Polarsが列を並列に読み込み、Pandasの「Python objectのオーバーヘッドがある行指向のNumPy配列」よりコンパクトなArrow列指向形式で保持するためです。
GroupBy集計(1,000万行、5グループ)
| Library | Time |
|---|---|
| Pandas | 1.8s |
| Polars | 0.22s |
Polarsはgroup-byを5〜10倍速く完了します。全CPUコアを使った並列ハッシュ集計が主因です。Pandasは単一スレッドで各グループを順に処理します。
ソート(1,000万行)
| Library | Time |
|---|---|
| Pandas | 3.4s |
| Polars | 0.29s |
ソートは性能差が最大になりやすく、Polarsは最大11倍速いことがあります。PandasのソートはシングルスレッドのNumPyソート実装に依存しており、ここが大きなボトルネックになります。
join(1,000万行と100万行の2つのDataFrame)
| Library | Time |
|---|---|
| Pandas | 2.1s |
| Polars | 0.35s |
Polarsのjoinは、join種別やキーのカーディナリティにより3〜8倍速くなります。分析ワークロードでよくある「大きいfactと小さいdimensionの結合」に対し、並列ハッシュjoin実装が特に効果的です。
性能に関する要点
10万行未満ならどちらも体感は即時です。差が意味を持ち始めるのは100万行あたりからで、データが大きくなるほどギャップは広がります。1台のマシンで1,000万行超を日常的に扱うなら、待ち時間が減るだけでPolarsは大きな生産性向上になります。
メモリ使用量:Polarsが軽量でいられる理由
メモリ効率はPolars最大の強みの1つです:
-
Apache Arrow列指向フォーマット:列ごとに連続したメモリブロックに保存されます。Pandasのblock-managerよりキャッシュ効率がよく、文字列や混在型でのPython objectオーバーヘッドも避けられます。
-
遅延評価で中間コピーを回避:Pandasではチェーンされた操作ごとに新しいコピーが作られます。5ステップの変換パイプラインならDataFrameのコピーを5つ確保する可能性があります。Polarsのlazy modeは最適化済みの計画を構築し、中間アロケーションを最小化します。
-
Projection pushdown:Parquetを読む、またはlazy scanする場合、Polarsはクエリで使う列だけをロードします。Pandasはすべて読み込みます。
-
Predicate pushdown:フィルタ条件をデータソース側に押し込みます。Parquetを10%の行に絞るなら、Polarsは一致するrow groupだけを読み込みます。Pandasは全行を読んでからメモリ上でフィルタします。
-
Streaming execution:RAMより大きいデータセットでも、バッチでストリーミング処理でき、全量をメモリに載せる必要がありません。
実務的には、16GBマシンでPandasがOut of Memoryになるパイプラインが、Polarsなら4〜6GB程度で余裕を持って走ることがあります。
遅延評価:Polarsクエリオプティマイザ
遅延評価は、PolarsとPandasを最も根本的に分ける機能です。PolarsのDataFrameで .lazy() を呼ぶ(または scan_csv / scan_parquet を使う)と、操作は即時に実行されません。代わりにPolarsは論理プラン(操作の有向グラフ)を構築し、実行前に最適化します。
オプティマイザはいくつかの変換を自動で行います:
# This lazy pipeline gets automatically optimized
result = (
pl.scan_parquet("huge_dataset.parquet") # 100 columns, 500M rows
.filter(pl.col("country") == "US") # Optimizer pushes this to file scan
.select("name", "revenue", "country") # Optimizer projects only 3 columns
.group_by("name")
.agg(pl.col("revenue").sum())
.sort("revenue", descending=True)
.head(20)
.collect()
)このパイプラインに対してオプティマイザが行うこと:
- Projection pushdown:Parquetから "name" / "revenue" / "country" だけを読む(残り97列は無視)
- Predicate pushdown:
country == "US"をParquetのrow-groupレベルで適用し、USレコードを含まないチャンクを丸ごとスキップ - Common subexpression elimination:同一expressionが複数回現れる場合、計算結果を再利用
- Join reordering:複数joinが連鎖する場合、最も効率の良い順序を選択
実行前に最適化済みプランを確認できます:
plan = (
pl.scan_parquet("data.parquet")
.filter(pl.col("value") > 100)
.select("id", "value")
)
print(plan.explain(optimized=True))Pandasにはこれに相当する仕組みがありません。Pandasの操作はすべて即時実行で、最適化は開発者が手動で行う必要があります。
エコシステムと互換性
エコシステムでPandasが勝つ場面
Pandasは17年かけて築かれた無類のエコシステムを持ちます:
- scikit-learn:入力としてPandas DataFrameを前提にしていることが多い。PolarsからPandasへ変換して学習することは可能ですが、ひと手間が摩擦になります。
- matplotlib / seaborn:Pandas DataFrameやSeriesをそのまま受け取れます。Polarsは変換が必要です。
- statsmodels:PandasとNumPyを前提に構築。Polarsのネイティブサポートはありません。
- Jupyter integration:Pandas DataFrameはノートブックで標準的にレンダリングされます。Polarsも見やすく表示されますが、一部の拡張はPandas前提です。
- ファイル形式サポート:PandasはExcel、HDF5、SQL databases、clipboard、fixed-width textなど多様。PolarsはCSV、Parquet、JSON、IPC/Arrow、Avro、databasesなどをサポートしますが、Excelはネイティブではありません(変換が必要)。
- Google Colab / cloud notebooks:多くのクラウド環境でプリインストールされ、前提として扱われがちです。
Polarsが追いついている領域
Polarsの周辺は急速に成長しています:
- DuckDB integration:DuckDBはPolars DataFrameをコピーなしでSQLクエリできます。SQLとexpressionワークフローを組み合わせられます。
- Streamlit:Polarsをネイティブサポート。
pl.DataFrameをそのまま表示関数に渡せます。 - Arrow ecosystem:Apache Arrowを扱えるツール(Spark、DuckDB、DataFusionなど)とPolarsはゼロコピーでデータ交換できます。
- Conversion methods:
df.to_pandas()とpl.from_pandas()により、両者の切り替えは容易です。
PyGWalkerによるビジュアル探索
PolarsとPandasのギャップを埋めるツールの1つが、PyGWalker (opens in a new tab)です。PyGWalkerはオープンソースのPythonライブラリで、任意のDataFrameをJupyter notebooks内でTableau風のインタラクティブ可視化UIに変換します。PyGWalkerはPandasとPolarsの両方のDataFrameをネイティブに扱えるため、どちらで処理していても視覚的に探索できます。
import pygwalker as pyg
# Works with Pandas
import pandas as pd
df_pandas = pd.read_csv("data.csv")
pyg.walk(df_pandas)
# Also works with Polars
import polars as pl
df_polars = pl.read_csv("data.csv")
pyg.walk(df_polars)これは、Polarsで高速に処理したあと、プロットコードを書かずにパターン・外れ値・分布を視覚的に確認したいワークフローで特に有用です。手元のDataFrameの上にドラッグ&ドロップのチャート作成環境を提供します。
学習コスト
PandasからPolarsへ
すでにPandasを知っているなら、Polarsの習得は実際に使いながらで約1〜2週間程度で「慣れる」ことが多いです。DataFrame、列、フィルタ、グループ化、joinといった中核概念は同じです。変わるのは構文とメンタルモデルです。
内面化すべき主な違い:
-
No index:PolarsのDataFrameには行インデックスがありません。Pandasの
.loc[]/.iloc[]/set_index()に強く依存している場合は調整が必要です。Polarsはfilter()と列ベースの選択で統一します。 -
Expression-based API:
df["col"]の代わりにpl.col("col")を使います。expressionは合成でき、最適化可能です。 -
代入よりメソッドチェーン:PolarsはDataFrameを行ごとにミューテートするより、メソッドチェーンでパイプラインを組み立てることを推奨します。
-
ファイルscanはlazyが基本:
scan_csv()/scan_parquet()はlazy frameを返します。実行には.collect()が必要です。 -
厳密な型:Polarsはデータ型に厳格です。Pandasのobject dtypeのように、整数と文字列が同じ列に混ざることを許しません(Pandasでも推奨はされませんが、起こりがちです)。
ゼロから始める場合
どちらも未経験なら、Polarsのほうが学びやすいという見方もできます。expression APIがより一貫しており(Pandasでバージョンによって変わった df.groupby と df.agg のパターンに迷うことが少ない)、インデックスがないことでPandas特有の落とし穴(予期せぬindex alignment、index reset、多段インデックスの混乱)を避けられます。
ただし学習リソースはPandasが圧倒的に多いです。書籍、大学講義、Stack Overflow回答、チュートリアルが充実しています。Polarsのドキュメントも良質ですが、量ではまだ小さいです。
Pandasを使うべきとき
Pandasが適切なのは次のような場合です:
- データがメモリに収まり、100万行未満:Pandasで十分速く、エコシステムの利点が大きい
- MLエコシステムとの深い統合が必要:scikit-learn、statsmodelsなど多くがPandas DataFrameを前提にしている
- チームがすでにPandasに習熟している:小〜中規模データでは、再教育コストが性能メリットを上回ることがある
- Excelを頻繁に扱う:Pandasの
read_excel()/to_excel()は実績がある - ニッチなI/O形式が必要:HDF5、Stata、SAS、SPSS、fixed-width textなど、Polarsが未対応の形式がある
- 小さなデータのノートブック探索:小さなCSVでの素早いアドホック分析では、慣れと統合の強さが実利になる
Polarsを使うべきとき
Polarsが適切なのは次のような場合です:
- 100万行超を日常的に扱う:性能差が意味を持ち、データが大きいほど差が広がる
- データパイプラインを構築している:遅延評価とクエリ最適化により、手動チューニングなしで高速化・効率化できる
- メモリが制約:Polarsはメモリ使用量が小さく、同じハードでより大きいデータを扱える
- 複雑さなしに並列性が欲しい:Polarsは自動並列化。
multiprocessingもdaskもインフラ変更も不要 - Parquetを扱うことが多い:Parquetでのpredicate / projection pushdownが大きな効率改善になる
- レガシーのPandasコードがない新規プロジェクト:移行コストがなく、Polars APIはクリーンで一貫している
- Arrow互換ツールへ渡す前処理:DuckDB、Spark、DataFusionなどArrow ecosystemのツールとゼロコピーで連携できる
両方使える?ハイブリッドアプローチ
多くのチームはハイブリッドを採用します。重い前処理はPolarsで行い、可視化やML学習はPandasに変換して実行します。変換は軽量で高速です。
import polars as pl
import pandas as pd
# Process data with Polars (fast)
processed = (
pl.scan_parquet("large_dataset.parquet")
.filter(pl.col("year") >= 2024)
.group_by("category")
.agg(
pl.col("revenue").sum().alias("total_revenue"),
pl.col("orders").count().alias("order_count")
)
.sort("total_revenue", descending=True)
.collect()
)
# Convert to Pandas for ML or visualization (small result set)
pandas_df = processed.to_pandas()
# Use with scikit-learn
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(pandas_df[["order_count"]], pandas_df["total_revenue"])このパターンなら、データ整形はPolarsの速度を享受しつつ、後段のタスクではPandasエコシステムを使えます。集計後の結果が小さければ、変換オーバーヘッドは無視できる程度です。
RunCellによるAI支援データ分析
PolarsでもPandasでも、Jupyter notebooksでの作業はAI支援で加速できます。RunCell (opens in a new tab) はJupyter向けに作られたAI agentで、データ分析コードの作成・デバッグ・最適化を支援します。PandasとPolarsの両方の構文を理解し、タスクに応じて最も効率的なアプローチ(PandasよりPolarsパイプラインが有利な場面の提案など)を提示できます。両ライブラリを頻繁に行き来するなら、両方を理解するAIコーディング支援は摩擦を大きく減らせます。
移行ガイド:PandasからPolarsへ
既存のPandasコードをPolarsへ移行することを検討している場合に備えて、よくある操作の対応表を示します:
| Pandas | Polars |
|---|---|
df["col"] | df.select("col") or pl.col("col") |
df[df["col"] > 5] | df.filter(pl.col("col") > 5) |
df.groupby("col").sum() | df.group_by("col").agg(pl.all().sum()) |
df.sort_values("col") | df.sort("col") |
df.merge(other, on="key") | df.join(other, on="key") |
df["new"] = df["a"] + df["b"] | df.with_columns((pl.col("a") + pl.col("b")).alias("new")) |
df.dropna() | df.drop_nulls() |
df.fillna(0) | df.fill_null(0) |
df.rename(columns={"a": "b"}) | df.rename({"a": "b"}) |
df.apply(func) | df.select(pl.col("col").map_elements(func)) |
pd.read_csv("file.csv") | pl.read_csv("file.csv") |
pd.read_parquet("file.parquet") | pl.scan_parquet("file.parquet").collect() |
df.to_csv("out.csv") | df.write_csv("out.csv") |
df.head() | df.head() |
df.describe() | df.describe() |
両ライブラリの今後
Pandasが消えることはありません。2.xリリースでは性能改善が続き、任意のArrow backendにより、特定の操作ではPolarsとの差が縮まっています。Pandas上に築かれた巨大なエコシステムが、今後も長く関連性を保証します。
Polarsは急速に勢いを増しています。専業企業(Polars Inc.)の支援、定期的なリリース、増えるコミュニティ貢献、そして本番データエンジニアリングパイプラインでの採用増により、モダンなデータスタックの標準ツールになりつつあります。GPU acceleration、SQLサポートの改善、より深いエコシステム統合がロードマップにあります。
トレンドは明確です。Pythonのデータエコシステムは共通メモリフォーマットとしてApache Arrowへ向かっており、両ライブラリもその標準に収束しています。つまりPolars、Pandas、DuckDB、その他ツール間の相互運用性は今後さらに良くなります。
FAQ
まとめ
2026年にPolarsとPandasのどちらを選ぶかは、「どちらが普遍的に優れているか」ではありません。仕事に対して適切な道具を当てる話です。
Pandasは、小〜中規模データ、scikit-learnに依存するMLワークフロー、素早い探索的分析、そして性能よりチームの習熟度が重要なプロジェクトにおいて、依然として最良の選択肢です。エコシステムは比類なく、Pandas 2.xも改善を続けています。
Polarsは、性能が重要な場面――大規模データ、データパイプライン、メモリ制約のある環境、遅延評価と自動並列性の恩恵を受ける新規プロジェクト――でより良い選択です。速度の優位は僅差ではなく、しばしば桁違いです。
多くのチームにとって最も効果的なのは両方を使うことです。速度が効くところはPolarsで処理し、エコシステムの要件があるところはPandasに変換し、さらに PyGWalker (opens in a new tab) のように両方のDataFrameに対応したツールで視覚的探索を行う。PythonデータエコシステムはApache Arrowへ収束しており、こうした相互運用は年々容易になっています。
どちらを選んでも、Python開発者が「Pythonエコシステムを離れずにPandasの本格的な高性能代替」を手にしたことは、データ分析にとって大きな前進です。