Slide 1

Slide 1 text

Polarsの成長: v0.14からv1.0までの変遷と今後の展望 2024/07/12 Polars Data Crunch #2 Higuchi Kokoro

Slide 2

Slide 2 text

今日の内容 ゴール Polarsのアップデートの歴史と将来像がわかる 💡 Polarsに追加された便利な機能がキャッチアップできる ✨ お品書き 1. これまでのPolarsのアップデートの歴史と傾向把握 2. アップデートのキャッチアップ 1. Polars1.0と今後の展望 2. 過去の重要なアップデートのサマリ

Slide 3

Slide 3 text

自己紹介 Higuchi Kokoro Data Scientist@Commune X: @zerebom_3 担当領域: 推薦・検索・プロダク トのデータ分析・LLMなど ELDEN RINGにハマってます

Slide 4

Slide 4 text

Polarsのアップデートの歴史と変更の傾向

Slide 5

Slide 5 text

前準備: リリースのデータセット化 リリースの傾向を定量評価するために、PyGitHub経由でRelease Noteを抽出 正規表現でカテゴリごとのPR数などを取得 今回はPythonのリリースのみを集計 Ref: https://github.com/pola-rs/polars/releases

Slide 6

Slide 6 text

取得コード from github import Github g = Github(token) repo = g.get_repo("pola-rs/polars") releases = repo.get_releases() data = [] for release in tqdm(releases): version = release.tag_name date = release.published_at data.append( { "Version": version, "Date": date.strftime("%Y-%m-%d"), "Month": date.strftime("%Y-%m"), "Description": release.body, } ) df = pl.DataFrame(data) release_notes = df["Description"].to_list() pattern = r"##\s*([^\n]+)\s*((?:(?!##).|\n)*)" dict_list = [] for note in release_notes: dic = {} matches = re.findall(pattern, note) for match in matches: dic[remove_emoji(match[0]).strip()] \ = len(re.findall(r"- ", match[1])) dict_list.append(dic) release_cnt_df = pl.from_dicts(dict_list) df = ( pl.concat( [df,release_cnt_df], how="horizontal" ) .filter(pl.col("Language") == "py") .drop("Description") )

Slide 7

Slide 7 text

アップデートの頻度 2022/10: 0.14からリリース開始 各マイナーバージョンアップデート: 15-30回ほどのリリース リリース間隔: 初期は60日程度。直近は 100-180日

Slide 8

Slide 8 text

アップデートの傾向 PRのマージPR数が増加傾向 Bug fixesが減少 DeprecationsやEnhancementsの割合が増加 → 徐々にライブラリが成熟していることを示唆していそう

Slide 9

Slide 9 text

Polars 1.0.0の変更点と今後の展望

Slide 10

Slide 10 text

Polars 1.0.0の変更点と今後の展望 GPU 対応 ⚡ NVIDIA RAPIDSによる高速化 .collect(gpu=True) で呼び出し可能にする予定、準備中 Polars Cloudの導入 ☁️ ホスティングやスケーリングをしてくれるマネージドサービス 型の厳密化 📏 pl.Series() の初期化時に型が混合してるとError `replace()は前後の型がマッチしていないとError → 総論、大規模なデータをプロダクション品質で分析・処理できるライブラリに refs: https://pola.rs/posts/announcing-polars-1/

Slide 11

Slide 11 text

Polars 1.0.0への追従方法 Update Guideを参照し、書き換える もしくは polars-upgrade ツールを使用し、自動変換する pre-commit hookにも対応 ref: https://github.com/MarcoGorelli/polars-upgrade pip install polars-upgrade polars-upgrade my_project --target-version=1.0

Slide 12

Slide 12 text

Versioning philosophy 1.0にアップデートしたものの、設計に欠陥があれば破壊的な変更を加える ただし、頻度と深刻さは時間とともに大幅に減少すると予想 RustのNightlyシステムに依存している箇所は、将来的に変更可能性あり 詳しいルールはVersioningを参照

Slide 13

Slide 13 text

過去の重要なアップデート https://pola.rs/posts/ の"Polars in Aggregate"をチェック!

Slide 14

Slide 14 text

外部ライブラリとの連携強化 hvPlot連携 高レベル可視化ライブラリ hvPlot を 直接呼び出せるように PyTorch & JAX連携 Tensorへ直接・高速に変換出来るよう に その他連携ライブラリ Great Tables(dfの可視化) Hugging Face scikit-learn df = pl.DataFrame({"x": range(10), "y": range(10)}) df.plot.line(x="x", y="y") df = pl.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}) torch_tensor = df.to_torch() jax_array = df.to_jax()

Slide 15

Slide 15 text

APIの充実 Struct操作の改善 構造体の属性に対して複数操作可能に Array操作の改善 df.with_columns( number_of_twos=pl.col("a").arr.count_matches(2) ) count_matches や contains などの 便利なAPIが追加 SQL機能の拡張 pl.sql() では名前空間に定義された 複数のdfを呼び出せる df.sql() でdfを直接操作可能 REGEXP や LIKE 等の構文も追加 df.select( pl.col("item").struct.with_fields( pl.field("name").str.to_uppercase(), pl.field("car").fill_null("Mazda") ) ) df.sql("SELECT * FROM df WHERE a > 5") pl.sql(""" SELECT df1.*, d FROM df1 INNER JOIN df2 USING (a) WHERE a > 1 AND EXTRACT(year FROM c) < 2050 """).collect()

Slide 16

Slide 16 text

パフォーマンスの向上 CSV/Excel書き込みの高速化 with_columns の最適化 df.lazy() .with_columns(height_per_year=pl.col("height") / pl.col("age")) .with_columns(height_mean=pl.lit(0)) .with_columns(age=pl.col("age") - 18) .with_columns(height_mean=pl.col("height").mean()) 複数のwith_columns()は内部で1つのクエリとして最適化

Slide 17

Slide 17 text

まとめ Polars 1.0がリリースされた 🎉 下記のような継続的改善が行われている 機能拡張と性能改善 外部ライブラリとの連携強化 ユーザーフレンドリーなAPIの進化 今後の展望 GPU対応による更なる高速化 Polars Cloudでのスケーラビリティ向上 より型安全で堅牢なライブラリに

Slide 18

Slide 18 text

参考資料 Polars Blog GitHub Repository