import polars as pl
df = pl.read_csv("data/iris.csv")はじめに
Polarsは、高速で効率的なデータフレーム操作を可能にするPythonのライブラリです。
これまでRでPolarsを使う方法や、Python環境の構築に関する記事で何回か言及してきたものの、いまだにPythonにおけるPolarsについてはまとめてきませんでした。
この記事では、Rユーザー、特にTidyverseに慣れた方々がPolarsを使い始めるための基本的な手順とコード例を紹介します。
これまでの記事に関しては以下をご覧ください。

Polarsのインストール
PolarsはPythonのパッケージとして提供されており、以下のコマンドでインストールできます。
pip install polarsuvを使っている場合は以下でも可能です。
uv add polars基本的な使い方
ここからは、Tidyverseでよく使われる関数を挙げながら、Polarsでの対応する操作を紹介します。
データの読み込み(read_csv)
まずはデータの読み込みから始めます。以下の例では、CSVファイルを読み込んでいます。
これが一番基本的な読み込み方法です。Rのread_csv()関数に相当します。
Polarsでデータを読み込む場合、shift-jisのファイルを読み込むことはできません。その場合はPandasを使って読み込み、PolarsのDataFrameに変換する必要があります。
import pandas as pd
import polars as pl
pdf = pd.read_csv("data_shift_jis.csv", encoding="shift-jis")
df = pl.from_pandas(pdf)データの確認(head, tail)
データの先頭や末尾を確認するには、head()とtail()メソッドを使用します。
# 先頭5行を表示
print(df.head())
# 末尾5行を表示
print(df.tail())shape: (5, 5)
┌──────────────┬─────────────┬──────────────┬─────────────┬─────────┐
│ Sepal.Length ┆ Sepal.Width ┆ Petal.Length ┆ Petal.Width ┆ Species │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═════════════╪══════════════╪═════════════╪═════════╡
│ 5.1 ┆ 3.5 ┆ 1.4 ┆ 0.2 ┆ setosa │
│ 4.9 ┆ 3.0 ┆ 1.4 ┆ 0.2 ┆ setosa │
│ 4.7 ┆ 3.2 ┆ 1.3 ┆ 0.2 ┆ setosa │
│ 4.6 ┆ 3.1 ┆ 1.5 ┆ 0.2 ┆ setosa │
│ 5.0 ┆ 3.6 ┆ 1.4 ┆ 0.2 ┆ setosa │
└──────────────┴─────────────┴──────────────┴─────────────┴─────────┘
shape: (5, 5)
┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┐
│ Sepal.Length ┆ Sepal.Width ┆ Petal.Length ┆ Petal.Width ┆ Species │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╡
│ 6.7 ┆ 3.0 ┆ 5.2 ┆ 2.3 ┆ virginica │
│ 6.3 ┆ 2.5 ┆ 5.0 ┆ 1.9 ┆ virginica │
│ 6.5 ┆ 3.0 ┆ 5.2 ┆ 2.0 ┆ virginica │
│ 6.2 ┆ 3.4 ┆ 5.4 ┆ 2.3 ┆ virginica │
│ 5.9 ┆ 3.0 ┆ 5.1 ┆ 1.8 ┆ virginica │
└──────────────┴─────────────┴──────────────┴─────────────┴───────────┘
列の選択(select)
Polarsで特定の列を選択するには、select()メソッドを使用します。
# "sepal_length"と"sepal_width"の列を選択
selected_df = df.select(["Sepal.Length", "Sepal.Width"])
print(selected_df)shape: (150, 2)
┌──────────────┬─────────────┐
│ Sepal.Length ┆ Sepal.Width │
│ --- ┆ --- │
│ f64 ┆ f64 │
╞══════════════╪═════════════╡
│ 5.1 ┆ 3.5 │
│ 4.9 ┆ 3.0 │
│ 4.7 ┆ 3.2 │
│ 4.6 ┆ 3.1 │
│ 5.0 ┆ 3.6 │
│ … ┆ … │
│ 6.7 ┆ 3.0 │
│ 6.3 ┆ 2.5 │
│ 6.5 ┆ 3.0 │
│ 6.2 ┆ 3.4 │
│ 5.9 ┆ 3.0 │
└──────────────┴─────────────┘
Rでは列名を単にベクトルで指定しますが、Polarsではリストで指定します。ダブルクォーテーションで囲まなければならないのも、Rユーザーにとっては地味に面倒ですが…。
フィルタリング(filter)
データを条件でフィルタリングするには、filter()メソッドを使用します。
# "Sepal.Length"が5.0より大きい行をフィルタリング
filtered_df = df.filter(pl.col("Sepal.Length") > 5.0)
print(filtered_df)shape: (118, 5)
┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┐
│ Sepal.Length ┆ Sepal.Width ┆ Petal.Length ┆ Petal.Width ┆ Species │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╡
│ 5.1 ┆ 3.5 ┆ 1.4 ┆ 0.2 ┆ setosa │
│ 5.4 ┆ 3.9 ┆ 1.7 ┆ 0.4 ┆ setosa │
│ 5.4 ┆ 3.7 ┆ 1.5 ┆ 0.2 ┆ setosa │
│ 5.8 ┆ 4.0 ┆ 1.2 ┆ 0.2 ┆ setosa │
│ 5.7 ┆ 4.4 ┆ 1.5 ┆ 0.4 ┆ setosa │
│ … ┆ … ┆ … ┆ … ┆ … │
│ 6.7 ┆ 3.0 ┆ 5.2 ┆ 2.3 ┆ virginica │
│ 6.3 ┆ 2.5 ┆ 5.0 ┆ 1.9 ┆ virginica │
│ 6.5 ┆ 3.0 ┆ 5.2 ┆ 2.0 ┆ virginica │
│ 6.2 ┆ 3.4 ┆ 5.4 ┆ 2.3 ┆ virginica │
│ 5.9 ┆ 3.0 ┆ 5.1 ┆ 1.8 ┆ virginica │
└──────────────┴─────────────┴──────────────┴─────────────┴───────────┘
Rのfilter()ではfilter(Sepal.Length > 5.0)のように書きますが、Polarsではpl.colを使ってpl.col("Sepal.Length")のように列を指定します。正直こちらもRの方が書きやすいなとか思ってしまいますが、慣れの問題でしょうか。
新しい列の追加(mutate)
新しい列を追加するには、with_columns()メソッドを使用します。Rのmutate()に相当します。
# "Sepal.Ratio"という新しい列を追加
mutated_df = df.with_columns(
(pl.col("Sepal.Length") / pl.col("Sepal.Width")).alias("Sepal.Ratio")
).select(["Sepal.Length", "Sepal.Width", "Sepal.Ratio"])
print(mutated_df)shape: (150, 3)
┌──────────────┬─────────────┬─────────────┐
│ Sepal.Length ┆ Sepal.Width ┆ Sepal.Ratio │
│ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 │
╞══════════════╪═════════════╪═════════════╡
│ 5.1 ┆ 3.5 ┆ 1.457143 │
│ 4.9 ┆ 3.0 ┆ 1.633333 │
│ 4.7 ┆ 3.2 ┆ 1.46875 │
│ 4.6 ┆ 3.1 ┆ 1.483871 │
│ 5.0 ┆ 3.6 ┆ 1.388889 │
│ … ┆ … ┆ … │
│ 6.7 ┆ 3.0 ┆ 2.233333 │
│ 6.3 ┆ 2.5 ┆ 2.52 │
│ 6.5 ┆ 3.0 ┆ 2.166667 │
│ 6.2 ┆ 3.4 ┆ 1.823529 │
│ 5.9 ┆ 3.0 ┆ 1.966667 │
└──────────────┴─────────────┴─────────────┘
Rと異なる点として、Rでは先に列名を指定し、その後に計算式を書くのに対し、Polarsでは計算式を先に書き、その後にalias()で列名を指定します。
また、作った列を見やすくするために、ちゃっかりselect()をつなげて必要な列だけを抽出しています。Rのパイプでつなげて処理できるのと同様に、Polarsでもメソッドチェーンでつなげて処理できます。
グループ化と集計(group_by, summarise)
データをグループ化して集計するには、group_by()とagg()メソッドを使用します。Rで言うところのgroup_by()とsummarise()に相当します。
# "Species"でグループ化し、"Sepal.Length"の平均を計算
grouped_df = df.group_by("Species").agg(
pl.col("Sepal.Length").mean().alias("Avg_Sepal_Length")
)
print(grouped_df)shape: (3, 2)
┌────────────┬──────────────────┐
│ Species ┆ Avg_Sepal_Length │
│ --- ┆ --- │
│ str ┆ f64 │
╞════════════╪══════════════════╡
│ setosa ┆ 5.006 │
│ virginica ┆ 6.588 │
│ versicolor ┆ 5.936 │
└────────────┴──────────────────┘
ここでもwith_columns()と同様に、集計結果の列名をalias()で指定しています。
データの並び替え(arrange)
データを特定の列で並び替えるには、sort()メソッドを使用します。Rのarrange()に相当します。
# "Sepal.Length"で昇順に並び替え
sorted_df = df.sort("Sepal.Length")
print(sorted_df)shape: (150, 5)
┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┐
│ Sepal.Length ┆ Sepal.Width ┆ Petal.Length ┆ Petal.Width ┆ Species │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╡
│ 4.3 ┆ 3.0 ┆ 1.1 ┆ 0.1 ┆ setosa │
│ 4.4 ┆ 2.9 ┆ 1.4 ┆ 0.2 ┆ setosa │
│ 4.4 ┆ 3.0 ┆ 1.3 ┆ 0.2 ┆ setosa │
│ 4.4 ┆ 3.2 ┆ 1.3 ┆ 0.2 ┆ setosa │
│ 4.5 ┆ 2.3 ┆ 1.3 ┆ 0.3 ┆ setosa │
│ … ┆ … ┆ … ┆ … ┆ … │
│ 7.7 ┆ 3.8 ┆ 6.7 ┆ 2.2 ┆ virginica │
│ 7.7 ┆ 2.6 ┆ 6.9 ┆ 2.3 ┆ virginica │
│ 7.7 ┆ 2.8 ┆ 6.7 ┆ 2.0 ┆ virginica │
│ 7.7 ┆ 3.0 ┆ 6.1 ┆ 2.3 ┆ virginica │
│ 7.9 ┆ 3.8 ┆ 6.4 ┆ 2.0 ┆ virginica │
└──────────────┴─────────────┴──────────────┴─────────────┴───────────┘
降順に並び替える場合は、descending=Trueを指定します。
# "Sepal.Length"で降順に並び替え
sorted_df_desc = df.sort("Sepal.Length", descending=True)
print(sorted_df_desc)shape: (150, 5)
┌──────────────┬─────────────┬──────────────┬─────────────┬───────────┐
│ Sepal.Length ┆ Sepal.Width ┆ Petal.Length ┆ Petal.Width ┆ Species │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ f64 ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═════════════╪══════════════╪═════════════╪═══════════╡
│ 7.9 ┆ 3.8 ┆ 6.4 ┆ 2.0 ┆ virginica │
│ 7.7 ┆ 3.8 ┆ 6.7 ┆ 2.2 ┆ virginica │
│ 7.7 ┆ 2.6 ┆ 6.9 ┆ 2.3 ┆ virginica │
│ 7.7 ┆ 2.8 ┆ 6.7 ┆ 2.0 ┆ virginica │
│ 7.7 ┆ 3.0 ┆ 6.1 ┆ 2.3 ┆ virginica │
│ … ┆ … ┆ … ┆ … ┆ … │
│ 4.5 ┆ 2.3 ┆ 1.3 ┆ 0.3 ┆ setosa │
│ 4.4 ┆ 2.9 ┆ 1.4 ┆ 0.2 ┆ setosa │
│ 4.4 ┆ 3.0 ┆ 1.3 ┆ 0.2 ┆ setosa │
│ 4.4 ┆ 3.2 ┆ 1.3 ┆ 0.2 ┆ setosa │
│ 4.3 ┆ 3.0 ┆ 1.1 ┆ 0.1 ┆ setosa │
└──────────────┴─────────────┴──────────────┴─────────────┴───────────┘
データの結合(join)
データフレームを結合するには、join()メソッドを使用します。Rのleft_join()やinner_join()に相当します。Rとは違って関数自体は同じですが、結合の種類をhow引数で指定します。
まずは左結合(left_join())の例を示します。
# 例として2つのデータフレームを作成
df1 = pl.DataFrame({
"key": [1, 2, 3],
"value1": ["A", "B", "C"]
})
df2 = pl.DataFrame({
"key": [2, 3, 4],
"value2": ["D", "E", "F"]
})
# df1とdf2を"key"列で左結合
joined_df = df1.join(df2, on="key", how="left")
print(joined_df)shape: (3, 3)
┌─────┬────────┬────────┐
│ key ┆ value1 ┆ value2 │
│ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ str │
╞═════╪════════╪════════╡
│ 1 ┆ A ┆ null │
│ 2 ┆ B ┆ D │
│ 3 ┆ C ┆ E │
└─────┴────────┴────────┘
次に、内部結合(inner_join())の例を示します。
# df1とdf2を"key"列で内部結合
joined_df_inner = df1.join(df2, on="key", how="inner")
print(joined_df_inner)shape: (2, 3)
┌─────┬────────┬────────┐
│ key ┆ value1 ┆ value2 │
│ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ str │
╞═════╪════════╪════════╡
│ 2 ┆ B ┆ D │
│ 3 ┆ C ┆ E │
└─────┴────────┴────────┘
次に、完全結合(full_join())の例を示します。
# df1とdf2を"key"列で完全結合
joined_df_full = df1.join(df2, on="key", how="full")
print(joined_df_full)shape: (4, 4)
┌──────┬────────┬───────────┬────────┐
│ key ┆ value1 ┆ key_right ┆ value2 │
│ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ i64 ┆ str │
╞══════╪════════╪═══════════╪════════╡
│ 2 ┆ B ┆ 2 ┆ D │
│ 3 ┆ C ┆ 3 ┆ E │
│ null ┆ null ┆ 4 ┆ F │
│ 1 ┆ A ┆ null ┆ null │
└──────┴────────┴───────────┴────────┘
最後に、準結合(semi_join())の例を示します1。
# df1とdf2を"key"列で準結合
joined_df_semi = df1.join(df2, on="key", how="semi")
print(joined_df_semi)shape: (2, 2)
┌─────┬────────┐
│ key ┆ value1 │
│ --- ┆ --- │
│ i64 ┆ str │
╞═════╪════════╡
│ 2 ┆ B │
│ 3 ┆ C │
└─────┴────────┘
テーブルの転置(pivot)
データフレームを転置するには、pivot()メソッドを使用します。Rのpivot_wider()やpivot_longer()に相当します。
# 例としてデータフレームを作成
df = pl.DataFrame({
"id": [1, 1, 2, 2],
"variable": ["A", "B", "A", "B"],
"value": [10, 20, 30, 40]
})
print(df)shape: (4, 3)
┌─────┬──────────┬───────┐
│ id ┆ variable ┆ value │
│ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ i64 │
╞═════╪══════════╪═══════╡
│ 1 ┆ A ┆ 10 │
│ 1 ┆ B ┆ 20 │
│ 2 ┆ A ┆ 30 │
│ 2 ┆ B ┆ 40 │
└─────┴──────────┴───────┘
まずは、pivot_wider()の例を示します。
# pivot_widerの例
pivoted_df = df.pivot(values="value", index="id", on="variable")
print(pivoted_df)shape: (2, 3)
┌─────┬─────┬─────┐
│ id ┆ A ┆ B │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1 ┆ 10 ┆ 20 │
│ 2 ┆ 30 ┆ 40 │
└─────┴─────┴─────┘
次に、ワイド形式にしたデータをpivot_longer()のように処理する例を示します。
# pivot_longerの例
melted_df = pivoted_df.unpivot(
index=["id"],
on=["A", "B"],
variable_name="variable",
value_name="value"
)
print(melted_df)shape: (4, 3)
┌─────┬──────────┬───────┐
│ id ┆ variable ┆ value │
│ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ i64 │
╞═════╪══════════╪═══════╡
│ 1 ┆ A ┆ 10 │
│ 2 ┆ A ┆ 30 │
│ 1 ┆ B ┆ 20 │
│ 2 ┆ B ┆ 40 │
└─────┴──────────┴───────┘
元のデータの形に戻りました。並べ替えたいときは先述のsort()メソッドを使ってください。
おわりに
以上がよく使うRのTidyverse関数とPolarsでの対応する操作の基本的な例です。
この記事では、RユーザーがPolarsを使い始めるための基本的な手順とコード例を紹介しました。Polarsは高速で効率的なデータ処理を可能にする強力なツールであり、Python環境でのデータ分析において有用です。
これまではずっと Rだけを使ってきましたが、いろいろ調べていくうちにPythonはそのユーザー数の多さから開発も活発であり、新しく便利なツールやライブラリが次々と登場しているなと感じることが多くなってきました。これからもRとPythonの両方を使い分けていきたいと思っています。
今後も必要に応じて追記していきますので、是非参考にしてみてください。
注
準結合とは、左のデータフレームの行が右のデータフレームに存在するかどうかでフィルタリングする結合方法です。↩︎