1. はじめに
遅まきながら、⭐️Polars🐻❄️⭐️ を触ってみたところ、何やら良すぎた! コレ知らんヤツが、データサイエンティスト!? チャンチャラおかしいわ、笑てまうやんけ!! とまで思ってしまったので、簡単に、Tipsをまとめてみました。Pandas🐼 は使えるけどね、という方々に向けて、両者のコードを並べて書いています。
(Kaggle ノートブック "Let's Play with 🌙 Polars 🐻❄️ & 🌙 Pandas 🐼"からの引用)
2. 何が良いんだい??
⭐️Polars🐻❄️⭐️ の何が良いんだい?? と思った方々に向けて、良いところをつらつらと書き綴っておきます。
- とにかく早い。
- データによるが、以下の通り、数十倍にも達し得る。
- データの規模が大きいほど、Pandas🐼 との差が顕著になる。
- メモリに乗りきらない大規模なデータも取り扱える。
- Pandas🐼 でもできないことはないが、より簡単な短いコードで同じことがやれる。
(Pandas🐼 は無駄に大きなメモリを使うので、大規模なデータを扱いづらい。)
- Pandas🐼 でもできないことはないが、より簡単な短いコードで同じことがやれる。
- 直感的に分かりやすい。
- Pandas🐼 よりも直感的に分かりやすい書き方で書ける。
- indexみたいなややこしい仕組みもない。
(Polars HPからの引用)
3. ⭐️Polars🐻❄️⭐️ の10Tips
では、本題です。ここでは、過去に、Kaggleで開催されたコンペ "Home Credit Default Risk" のデータセットを、⭐️Polars🐻❄️⭐️を使って処理してみます。その中で、以下の10個のTipsを紹介していきたいと思います。比較のため、Pandas🐼 のコードも併せて記載してあります。
- #001 ファイルを読み込む。
- #002 名前を指定して列を切り出す。
- #003 名前の一部を指定して列を切り出す。
- #004 データの型を指定して列を切り出す。
- #005 行の番号を指定して行を切り出す。
- #006 条件を指定して行を切り出す。
- #007 数値の列の基本的な統計量を求める。
- #008 数値以外の列のユニークな値毎の行の数を数える。
- #009 欠損値の数を数える。
- #010 欠損値を埋めあわせる。
#000 まずは準備。
まず、必要なパッケージをインストールして、インポートします。
# ⭐️Polars🐻❄️⭐️
%pip install -Uq polars
import polars as pl
import polars.selectors as cs
# Pandas🐼
import pandas as pd
これで、準備は完了です。
#001 ファイルを読み込む。
ファイルを読み込みます。
# ⭐️Polars🐻❄️⭐️
path_to_your_file = "/kaggle/input/home-credit-default-risk/application_train.csv"
df_pl = pl.read_csv(path_to_your_file)
df_pl
# Pandas🐼
path_to_your_file = "/kaggle/input/home-credit-default-risk/application_train.csv"
df_pd = pd.read_csv(path_to_your_file)
df_pd
#002 名前を指定して列を切り出す。
名前を指定して、列を切り出してみます。ここでは、例として、SK_ID_CURR
、TARGET
という名前の列を切り出してみます。
# ⭐️Polars🐻❄️⭐️
df_pl.select(pl.col(["SK_ID_CURR", "TARGET"]))
# Pandas🐼
df_pd[["SK_ID_CURR", "TARGET"]]
#003 名前の一部を指定して列を切り出す。
名前の一部を指定して、列を切り出してみます(正規表現を使った曖昧検索。正規表現が気になってきた方は、一度ググってみましょう。)。ここでは、例として、列の名前にCREDIT_BUREAU
というキーワードを含む列を切り出してみます。
# ⭐️Polars🐻❄️⭐️
df_pl.select(pl.col(r"^.*CREDIT_BUREAU.*$"))
# Pandas🐼
df_pd.filter(regex=r"^.*CREDIT_BUREAU.*$")
#004 データの型を指定して列を切り出す。
データの型を指定して、列を切り出してみます。ここでは、例として、文字列の値を含む列を切り出してみます。
# ⭐️Polars🐻❄️⭐️
df_pl.select(cs.string())
# Pandas🐼
df_pd.select_dtypes(include="object")
#005 行の番号を指定して行を切り出す。
行の番号を指定して、行を切り出してみます。ここでは、例として、2行目から7行目を切り出してみます。
# ⭐️Polars🐻❄️⭐️
df_pl.with_row_index().filter(pl.col("index").is_between(2, 7))
# Pandas🐼
df_pd.iloc[2:7+1]
#006 条件を指定して行を切り出す。
条件を指定して、行を切り出してみます。ここでは、例として、AMT_INCOME_TOTAL
が 1_000_000
以上の行を切り出してみます。
# ⭐️Polars🐻❄️⭐️
df_pl.filter(pl.col("AMT_INCOME_TOTAL") >= 1_000_000)
# Pandas🐼
df_pd[df_pd["AMT_INCOME_TOTAL"] >= 1_000_000]
#007 数値の列の基本的な統計量を求める。
数値の列の基本的な統計量(平均、分散、分位数、等)を求めてみます。
# ⭐️Polars🐻❄️⭐️
df_pl.select(cs.numeric()).describe()
# Pandas🐼
df_pd.select_dtypes(include="number").describe()
#008 数値以外の列のユニークな値毎の行の数を数える。
数値以外の列のユニークな値毎に行の数を数えてみます。
# ⭐️Polars🐻❄️⭐️
f_sliced = df_pl.select(~cs.numeric())
for col in df_sliced.columns:
with pl.Config(tbl_rows=1000):
print(df_sliced.select(pl.col(col).value_counts()))
print()
# Pandas🐼
df_sliced = df_pd.select_dtypes(exclude="number")
for col in df_sliced.columns:
print(df_sliced[col].value_counts(dropna=False))
print()
#009 欠損値の数を数える。
列毎に、欠損値の数を数えてみます。ここでは、より分かりやすくするため、値の欠損がある列だけを取り出し、グラフの形で表示するようにしています。
# ⭐️Polars🐻❄️⭐️
plt.figure(figsize=(8, 16))
sns.barplot(data=df_pl.null_count().melt(value_name="num_missing_values").filter(pl.col("num_missing_values") > 0),
y="variable",
x="num_missing_values",
hue="variable")
plt.show()
# Pandas🐼
df_missing_values = df_pd.isna().sum()
df_missing_values = df_missing_values[df_missing_values > 0]
plt.figure(figsize=(8, 16))
sns.barplot(y=df_missing_values.index,
x=df_missing_values.values,
hue=df_missing_values.index)
plt.show()
#010 欠損値を埋めあわせる。
欠損値を埋め合わせてみます。ここでは、例として、列 AMT_REQ_CREDIT_BUREAU_YEAR
の値を、① 定数 999
もしくは ② 中央値 で埋め合わせてみます。
# ⭐️Polars🐻❄️⭐️
df_pl = df_pl.with_columns(
pl.col("AMT_REQ_CREDIT_BUREAU_YEAR").fill_null(pl.lit(999)).name.suffix("_filled_with_constant"),
pl.col("AMT_REQ_CREDIT_BUREAU_YEAR").fill_null(pl.median("AMT_REQ_CREDIT_BUREAU_YEAR")).name.suffix("_filled_with_median"),
)
df_pl.select(pl.col(r"^.*AMT_REQ_CREDIT_BUREAU_YEAR.*$"))
# Pandas🐼
median = df_pd["AMT_REQ_CREDIT_BUREAU_YEAR"].median()
df_pd["AMT_REQ_CREDIT_BUREAU_YEAR_filled_with_constant"] = df_pd["AMT_REQ_CREDIT_BUREAU_YEAR"].fillna(value=999)
df_pd["AMT_REQ_CREDIT_BUREAU_YEAR_filled_with_median"] = df_pd["AMT_REQ_CREDIT_BUREAU_YEAR"].fillna(value=median)
df_pd.filter(regex=r"^.*AMT_REQ_CREDIT_BUREAU_YEAR.*$")
以上、10個のTipsでした。本当はもうちょっとあるんだけどね。というか、Polarsの本当の良いところは、まだ、他にあるんだけどね(Lazyとか、Lazyとか、・・・。)。それは、また、次回か、次次回で紹介したいと思います。
4. 参考
もしか、⭐️Polars🐻❄️⭐️ ラブ😍 になった方が居れば、こちらも、参考になりますので、眺めてみて下さい。大半は、英語ですが、字幕も出ますし、巷に翻訳してくれるソフトもたくさんあります。近くに、英語が分かる方がいらっしゃれば、翻訳をお願いしてみるのも一興です。この辺りを覚えられたら、一端のデータサイエンティストに一歩近づくことができます。ぜひ、見てみて下さい。
✏︎ Polars user guide
⭐️Polars🐻❄️⭐️ のユーザーガイドです。ここにある内容を全て写経したら、もはや、他は見なくても良いくらいです。英語ですが、すごく分かりやすいです。ロジカル、かつ、簡単に書いてあるので、英語分からなくても、コードを実行しながら追いかけていけば、余裕で理解できてしまいます。
✏︎ Ritchie Vink - Keynote Polars | PyCon Lithuania 2024
リトアニアで開催された、PyConの動画です。⭐️Polars🐻❄️⭐️ の著者、Ritchie Vinkさんが、素晴らしい Keynote で ⭐️Polars🐻❄️⭐️ を紹介してくれています。ご本人に興味がある方、ユーザーガイドはまだムズイ、という方、ぜひ、見てみて下さい。
✏︎ Let's Play with 🌙 Polars 🐻❄️ & 🌙 Pandas 🐼
この記事のベースとなっている、Kaggleのノートブックです。実際に、コードを実行して結果を見てみたい方は、これをコピーして、自身で動かしてみましょう。
✏︎ Thomas Bierhance: Polars - make the switch to lightning-fast dataframes
ドイツで開催された、PyConの動画です。その道のプロである、Thomas Bierhanceさんが、実際の仕事で、⭐️Polars🐻❄️⭐️ を導入した際に分かったメリットや(売り物になるようなレベルの)コードの書き方の例 などを、紹介してくれています。⭐️Polars🐻❄️⭐️ の基本が分かってきて、さあ、仕事で使っていこう、と思ってきた方にオススメの動画です。私も、彼のプレゼンから、コードの書き方を学びました。
✏︎ PyCon JP
PyConは、日本でも開催されています。 ⭐️Polars🐻❄️⭐️ が出てくるかは分かりませんが、折りを見て、参加してみるのも一興です。直接、社外の優秀な人の話を聞くと、刺激を受けて、あなたの成長につながります。
5. 最後に
生き物は必ず死を迎えます。それも、いつ訪れるのかわかりません。明日ミサイルが飛んでくるかも。時間は有限です。その中で、如何にやりたいことを成し遂げるのか、その鍵は時間の使い方にあります。計算機にやれる仕事はすべて、計算機にやってもらいましょう。そして、自分にしかできないこと、やりたいことをやりましょう。大事なことは、とにかく、自分のやりたいこと、楽しいことをやって、面白おかしく生きていくことです。