Polars vs. pandas – Python のデータフレームライブラリを徹底比較
Python DataFrame の進歩を過去 1 年間追い続けてきた方なら、大規模なデータセットを処理することを想定した強力な DataFrame ライブラリである Polars の名を耳にしたことがあるでしょう。

Spark、Dask、Ray といった大規模なデータセットを処理するための他のライブラリとは異なり、Polars は単一のマシンで使用することが想定されているため、pandas とよく比較されます。 しかし、Polars はデータの処理方法やその最適な用途などの多くの重要な点で pandas とは異なっています。 以下の記事では、これら 2 つの DataFrame ライブラリの技術的な違いを取り上げながら、それぞれの強みと制限を確認していきます。
より詳しい内容を知りたい場合は、以下に掲載する Polars の作者である Ritchie Vink とのインタビューもぜひご覧ください!
pandas ではなく Polars を使う理由 – Python データ分析の視点から
一言で言えば、「パフォーマンス」がその理由です。 Polars は非常に高速で処理できるようにゼロから構築されており、一般的な演算を pandas よりも 5~10 分速く処理できます。 また、Polars の演算に要するメモリは pandas よりはるかに小さく、演算の実行に必要な RAM が pandas ではデータセットサイズの約 5~10 倍であるのに対し、Polars では約 2~4 倍です。
他の DataFrame ライブラリと比較した Polars のパフォーマンスについては、こちらをご覧ください。 このリンク先に掲載されているように、Polars の処理速度は一般的な演算で pandas の 10~100 倍であり、実は全体的な処理速度が最も高い DataFrame ライブラリの 1 つです。 さらに、メモリ不足エラーを発生させずに処理できるデータセットの量も pandas より多いです。
Polars はなぜ高速?Python データフレーム最適化の秘密
このような結果は非常に目を見張るものがありますが、Polars が単一マシンで動作するにもかかわらず、これほどのパフォーマンスを得られる理由が気になりませんか? このライブラリは最初からパフォーマンスを念頭に設計されており、これはいくつかの手段によって達成されています。
Rust で書かれている
Polars について最もよく知られていることの 1 つに、C や C++ とほぼ同じ速度で処理される下位言語の Rust で書かれていることが挙げられます。 一方の pandas は Python ライブラリを基盤に構築されており、その中には NumPy が含まれています。 NumPy のコア部分は C で書かれているものの、カテゴリカルデータの文字列などの特定の型を Python がメモリ内で処理する方法に固有の問題が妨げとなり、それらの型を処理する際にパフォーマンスが低下します(詳細は、Wes McKinney によるこちらの素晴らしいブログ記事 をご覧ください)。
Rust を使用するメリットの 1 つに、安全な並行性を実現できることが挙げられます。つまり、できる限り並列処理を予測可能なものにするように設計されているのです。 そのため、Polars は複数の列を扱う複雑なクエリにもすべてのマシンのコアを安全に使用できます。Ritchie Vink が Polar のパフォーマンスを「困惑するほどの並列性」と評しているのはこのためです。 この並列性により、Polars のパフォーマンスは 1 つのコアのみを使って演算を実行する pandas よりも圧倒的に高くなります。 今年の PyCon DE での Nico Kreiling によるこちらの素晴らしい講演をご覧ください。Polars がこのパフォーマンスをどのように達成しているかが詳しく説明されています。
Arrow をベースとしている
Polars の目を見張るようなパフォーマンスには、言語に依存しないメモリ形式である Apache Arrow も貢献しています。 Arrow も実は Wes McKinney によって作成されたものです。その目的は、データサイズが爆発的に増加するのに伴って pandas で見つかった多数の問題に対応するためです。 pandas 2.0 のバックエンド(今年 3 月にリリースされたよりパフォーマンスの高い pandas のバージョン)でもあります。 ただし、このライブラリのバックエンドとなっている Arrow の動作はそれとは若干異なっています。pandas 2.0 は PyArrow ベースで作成されていますが、Polars チームが実装した Arrow は独自のものです。
Arrow ベースでデータライブラリを構築する主なメリットの 1 つには、相互運用性が挙げられます。 Arrow はライブラリ全体で使用されるメモリ内データの形式を標準化するように設計されており、以下のように、すでに多くの重要なライブラリやデータベースで使用されています。

この相互運用性により、データパイプラインの異なるステップ間でデータを受け渡す際にデータを別の形式に変換する必要性(データのシリアル化と逆シリアル化の必要性)がなくなるため、パフォーマンスが向上します。 また、2 つのプロセスがコピー操作なしで同じデータを共有できるため、メモリの効率も高まります。 シリアル化/逆シリアル化は、データワークフローにおける計算コストの 80~90% を占めると推定されており、Arrow の共通データ形式は Polars の大幅なパフォーマンス強化をもたらしています。
また、Arrow は pandas よりも幅広いデータ型を組み込みでサポートしています。 pandas は NumPy がベースになっているため、整数と浮動小数点の列の処理は得意ですが、他のデータ型の処理は苦手です。 対照的に、Arrow には日時、ブール値、バイナリ、さらにはリストを含む複雑な列型に対する高度なサポートが備わっています。 また、Arrow は欠損データをネイティブで処理できますが、NumPy では代替手段が必要です。
最後に付け加えますが、Arrow は列指向データストレージを使用するため、データ型を問わず、すべての列が連続するメモリブロックに格納されます。 そのため、並列性をより簡単に確保できるだけでなく、データ検索がさらに高速化されます。
クエリが最適化される
Polars のパフォーマンスを実現する重要な要素の 1 つには、コードの評価方法も挙げられます。 pandas は、演算を記述順に実行する即時(Eager)実行をデフォルトで使用します。 対照的に、Polars は即時実行と遅延実行の両方に対応しており、後者ではクエリオプティマイザーがすべての必要な演算を評価した後にコードを最も効率よく実行する方法を計画します。 この計画の対象には、演算の実行順の書き換えや冗長的な計算の削除といったさまざまな処理があります。 たとえば、Category
内のカテゴリ「A」と「B」のそれぞれから Number1
列の平均を取得する以下の式を見てみましょう。
( df .groupby(by = "Category").agg(pl.col("Number1").mean()) .filter(pl.col("Category").is_in(["A", "B"])) )
この式が即時実行される場合、DataFrame 全体に対して groupby
演算が不必要に実行され、その後で Category
によるフィルタリングが行われます。 遅延実行の場合は DataFrame をフィルタリングした後、必要なデータに対してのみ groupby
が実行されます。
API の表現力が豊かである
最後に付け加えますが、Polars には極めて表現力に優れた API が備わっており、ほとんどの場合は実行したい演算を何でも Polars メソッドとして表現できます。 しかし、pandas では比較的複雑な演算をラムダ式の形で apply
メソッドに渡さなければならないことが多々あります。 ここで問題となるのは、apply
メソッドが DataFrame の行をループで処理し、各行に対して順に演算を実行することです。 組み込みのメソッドを使用できると、列レベルで作業し、SIMD と呼ばれる別の形式の並列処理を活用できます。
pandas から乗り換えない理由
こんなにも素晴らしいことばかりなら、pandas から乗り換えない理由があるのかと疑問に思うかもしれません。 まだ結論を出すには早いですよ! Polars は極めて効率的なデータ変換処理が得意ですが、現時点ではデータ探索や機械学習パイプラインに組み込んで使用するには最適な選択肢ではありません。 このような分野では、依然として pandas が活躍しています。
その理由の 1 つには、Polars は Arrow を使用する他のパッケージとの相互運用性に優れているものの、ほとんどの Python データ可視化パッケージや、scikit-learn や PyTorch などの機械学習ライブラリにはまだ対応していないことが挙げられます。 Polars DataFrame からチャートを直接作成できる Plotly は唯一の例外です。
現在、そのようなパッケージで Python DataFrame 交換プロトコルを使って広範な DataFrame ライブラリをサポートできるようにするという解決策が議論されています。そのような解決策により、データサイエンスと機械学習のワークフローから pandas によるボトルネックがなくなる可能性があります。 しかし、これは比較的新しいアイデアであるため、このようなプロジェクトが実現するまでには時間がかかると思われます。
Polars と pandas に対応したツール
ここまでお読みになった方は、Polars を自分で試してみたくなったはずです! DataSpell にも PyCharm Professional 2023.2 にも Jupyter ノートブックで pandas と Polars の両方を扱うのに便利なツール一式が備わっています。 具体的には pandas と Polars DataFrame が対話的に操作できる形式で表示されるため、データを非常に迅速かつ快適に調査できます。
中でも私が気に入っているのは、DataFrame のすべての行と列を省略なしでスクロール表示できる機能、ワンクリックで DataFrame 値の集計を取得する機能、Markdown も含む多様な形式で DataFrame をエクスポートする機能です。
今すぐ DataSpell で Polars を体験しよう!30 日間無料トライアルはこちら
オリジナル(英語)ブログ投稿記事の作者: