Pythonはデータサイエンス分野で広く利用されており、その中でもPandasとPolarsはデータ処理ライブラリとして知られています。この記事では、PandasとPolarsの違い、それぞれの利点と欠点、そして具体的なコード例を通して、どちらのライブラリがどのような状況に適しているかを解説します。
PandasとPolarsの主な違い
PandasとPolarsの主な違いは、以下の表にまとめられます。
| 特徴 | Pandas | Polars |
|---|---|---|
| 開発言語 | Python (一部C) | Rust |
| 実行モデル | シングルスレッド/マルチプロセス(限定的) | マルチスレッド |
| メモリ使用量 | 比較的大量 | 比較的小量 |
| 処理速度 | 比較的低速 | 比較的高速 |
| APIスタイル | 柔軟、多様なメソッド | SQLライク、宣言的 |
| 機能 | 非常に豊富 | 比較的新しく、機能は限定的だが拡充中 |
| 成熟度 | 非常に成熟 | 開発途上 |
| 学習コスト | 比較的低い | やや高い(Rustの知識は不要) |
| データの不変性 | 可変(Mutable) | デフォルトで不変(Immutable) |
比較1: パフォーマンスとメモリ使用量
PolarsはRustで開発されており、マルチスレッド処理を基本としているため、Pandasよりも高速に動作します。特に大規模なデータセットを扱う場合、Polarsのパフォーマンスの優位性は顕著になります。
Pandasはデータをメモリ上に展開して処理を行うため、データセットのサイズによってはメモリ不足を引き起こす可能性があります。一方、Polarsはメモリ効率が良く、必要に応じてディスクへの書き出しも行うため、大規模データでもメモリ不足になりにくい設計です。
比較2: APIと機能
Pandasは非常に多くの機能を持ち、データの前処理、変換、集計、可視化など、幅広いタスクに対応できます。APIは柔軟で、さまざまなデータ操作を直感的に記述できます。
PolarsのAPIは、SQLに似た宣言的なスタイルを採用しています。これにより、処理の意図が明確になり、最適化が容易になります。機能面ではPandasに比べてまだ限定的ですが、基本的なデータ操作は十分にカバーされており、今後の機能拡張も期待できます。
比較3: データの不変性(Immutability)
PandasのDataFrameはデフォルトで可変(Mutable)です。つまり、DataFrameに対する操作はそのDataFrame自体を変更します。これは、意図しない副作用を引き起こす可能性があるため、注意が必要です。
一方、PolarsのDataFrameはデフォルトで不変(Immutable)です。操作は常に新しいDataFrameを返すため、元のデータが変更される心配はありません。これにより、コードの安全性と予測可能性が高まります。
Pandas と Polars の実装例
以下に、PandasとPolarsでCSVファイルを読み込み、特定の条件でフィルタリングし、グループ化して平均値を計算する例を示します。
前提
data.csvは以下のような構造のCSVファイルとします。
id,name,age,gender,salary 1,Alice,25,Female,50000 2,Bob,35,Male,60000 3,Charlie,45,Male,70000 4,Diana,30,Female,55000 5,Eve,28,Female,52000
Pandasのサンプルコード
まず、Pandasを使った基本的なコードを示します。
import pandas as pd # CSVファイルの読み込み df = pd.read_csv("data.csv") # 30歳より上のデータを抽出 filtered_df = df[df["age"] > 30] # 性別でグループ化し、給与の平均を計算 grouped_df = filtered_df.groupby("gender", as_index=False)[["salary"]].mean() print(grouped_df)
このコードでは、pd.read_csvでCSVファイルを読み込み、DataFrameを作成します。次に、df["age"] > 30という条件でフィルタリングを行い、groupbyメソッドで性別ごとにグループ化し、meanメソッドで給与の平均を計算しています。as_index=Falseはgroupbyのキー(gender)をindexにしないようにするためのオプションです。
次に、より複雑な処理を行う場合を考え、年齢を10歳刻みでグループ化し、性別と年齢層で平均給与と最大給与を算出します。
import pandas as pd # CSVファイルの読み込み df = pd.read_csv("data.csv") # 年齢層のカラムを追加 df["age_group"] = (df["age"] // 10) * 10 # 性別と年齢層でグループ化し、平均給与と最大給与を計算 grouped_df = df.groupby(["gender", "age_group"], as_index=False).agg( {"salary": ["mean", "max"]} ) #カラム名をわかりやすく変更 grouped_df.columns = ["gender", "age_group", "salary_mean", "salary_max"] print(grouped_df)
Python 実践データ分析 100本ノック 第2版 [ 下山輝昌 ]
Polarsのサンプルコード
次に、Polarsを使った基本的なコードを示します。
import polars as pl # CSVファイルの読み込み df = pl.read_csv("data.csv") # 30歳より上のデータを抽出 filtered_df = df.filter(pl.col("age") > 30) # 性別でグループ化し、給与の平均を計算 grouped_df = filtered_df.group_by("gender").agg(pl.col("salary").mean().alias("salary_mean")) print(grouped_df)
このコードでは、pl.read_csvでCSVファイルを読み込み、LazyFrameを作成します。filterメソッドでpl.col("age") > 30という条件のデータを抽出します。group_byメソッドで性別ごとにグループ化し、aggメソッド内でpl.col("salary").mean()として平均給与を計算しています。.alias("salary_mean")で結果のカラムに名前を付けています。
次に、Pandasの例と同様に、年齢を10歳刻みでグループ化し、性別と年齢層で平均給与と最大給与を算出します。
import polars as pl # CSVファイルの読み込み df = pl.read_csv("data.csv") # 年齢層のカラムを追加(with_columnsを利用) df = df.with_columns(((pl.col("age") // 10) * 10).alias("age_group")) # 性別と年齢層でグループ化し、平均給与と最大給与を計算 grouped_df = df.group_by(["gender", "age_group"]).agg( [pl.col("salary").mean().alias("salary_mean"), pl.col("salary").max().alias("salary_max")] ) print(grouped_df)
with_columnsを利用して、age_groupの計算と追加を同時に行います。
group_byとaggを利用してPandasと同様の処理を行います。
コードの量や複雑さにはそれほど差がなく、実装面ではどちらを選択しても問題ないことがわかります。
まとめ
PandasとPolarsはどちらも完成度が高く、実績もあるツールです。それぞれ異なる特徴と強みを持っています。
- Pandas: 豊富な機能、柔軟なAPI、高い成熟度を持ち、小規模から中規模のデータセットの処理に適しています。
- Polars: 高速な処理速度、少ないメモリ使用量、SQLライクなAPIを持ち、大規模データセットの処理に適しています。
どちらのライブラリを選択するかは、プロジェクトの要件、データセットのサイズ、パフォーマンスの重要性、そして開発者の習熟度によって異なります。多くの場合、Pandasから始めて、必要に応じてPolarsを検討するのが良いと思われます。最後にPythonのデータ解析を学習できるUdemyサイトを紹介します。
[PR]