見出し画像

Cookbooks

polarsの公式ドキュメントを読むと初めにCookbooksというのがあり、よくわからなかったので、調べた結果を本記事では備忘のため記録する。


Cookbooksとは

プログラミングの文脈での「Cookbook」は、以下のような意味を持つらしい。

  1. 実用的なコード例集:
    料理のレシピ本のように、特定のタスクを実行するための具体的なコード例や解決策を集めたもの。

  2. 問題解決のガイド:
    よくある問題や課題に対する実践的なアプローチを提供。

  3. 学習リソース:
    初心者から中級者までが、実際のシナリオでライブラリやフレームワークをどのように使用するかを説明。

  4. 参考資料:
    開発者が特定の機能を実装する際に参照できる、信頼性の高いリソースとして機能。

Polarsライブラリの文脈では、「Cookbooks」は以下のような内容を含むと考えられます:

  • データの読み込みと書き出し方法

  • データフレームの操作テクニック

  • 特定の分析や変換のための効率的なコード例

  • パフォーマンス最適化のヒント

  • EagerモードとLazyモードの使い分け方

これらの「レシピ」を参照することで、開発者はPolarsを効果的に使用するための実践的な知識を得ることができます。ドキュメントを読むだけでなく、実際のコード例を見ることで、ライブラリの機能をより深く理解し、自分のプロジェクトに適用することができる。

「Cookbook」アプローチは、多くのプログラミング言語やライブラリで採用されており、実践的な学習と問題解決を支援する効果的な方法として広く認識されているものである。


ということで、今回の「Eager」と「Lasy」について説明する。

Eager(即時評価)

  • データ処理が即座に実行される。

  • 各操作の結果がすぐに計算され、メモリに保持される。

  • 小規模から中規模のデータセットに適している。

  • 直感的で理解しやすいコードになりやすい。

Lazy(遅延評価)

  • データ処理の計画が作成されますが、実際の計算は後で行われる。

  • 複数の操作をまとめて最適化できるため、大規模なデータセットに適している。

  • メモリ使用量を抑えられる可能性がある。

  • 複雑なクエリや変換を効率的に処理できる。

例を挙げて違いを説明します:

Eagerモードの場合(Cargo.tomlを以下のように指定)

[dependencies]
polars = "0.43.0"

main.rs

use polars::prelude::*;

fn main() -> Result<(), PolarsError> {
    // サンプルデータフレーム
    let df = df! [
        "A" => [1, 2, 3, 4, 5],
        "B" => [10, 20, 30, 40, 50]
    ]?;

    println!("元のデータフレーム:\n{}", df);

    // Eager
    let mask = df["A"].gt(2)?;
    let eager_result = df.select(["A"])?.filter(&mask)?;
    println!("Eager result:\n{}", eager_result);

    Ok(())
}

結果

$ cargo run
   Compiling polars_project v0.1.0
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 7.20s
     Running `target\debug\polars_project.exe`
元のデータフレーム:
shape: (5, 2)
┌─────┬─────┐
│ A   ┆ B   │
│ --- ┆ --- │
│ i32 ┆ i32 │
╞═════╪═════╡
│ 110  │
│ 220  │
│ 330  │
│ 440  │
│ 550  │
└─────┴─────┘
Eager result:
shape: (3, 1)
┌─────┐
│ A   │
│ --- │
│ i32 │
╞═════╡
│ 3   │
│ 4   │
│ 5   │
└─────┘

Lazyモードの場合(Cargo.tomlを以下のように指定)

[dependencies]
polars = { version = "0.43.0", features = ["lazy"] }

main.rs

use polars::prelude::*;

fn main() -> Result<(), PolarsError> {
    let df = df! [
        "A" => [1, 2, 3, 4, 5],
        "B" => [10, 20, 30, 40, 50]
    ]?;

    println!("元のデータフレーム:\n{}", df);

    // Lazy
    let lazy_result = df.lazy()
        .select([col("A")])
        .filter(col("A").gt(lit(2)))
        .collect()?;
    println!("Lazy result:\n{}", lazy_result);

    Ok(())
}

結果

$ cargo run
   Compiling polars_project v0.1.0
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 9.80s
     Running `target\debug\polars_project.exe`
元のデータフレーム:
shape: (5, 2)
┌─────┬─────┐
│ A   ┆ B   │
│ --- ┆ --- │
│ i32 ┆ i32 │
╞═════╪═════╡
│ 110  │
│ 220  │
│ 330  │
│ 440  │
│ 550  │
└─────┴─────┘
Lazy result:
shape: (3, 1)
┌─────┐
│ A   │
│ --- │
│ i32 │
╞═════╡
│ 3   │
│ 4   │
│ 5   │
└─────┘


Eagerの場合、各操作(select、filter)が即座に実行されるが、Lazyの場合、collect()が呼ばれるまで実際の計算は行われません。

Lazyを使用すると、複雑な操作を最適化したり、大規模なデータセットを効率的な処理が可能である。ただし、小規模なデータセットや単純な操作の場合は、Eagerの方が直感的で使いやすいようです。

プロジェクトの要件や扱うデータの規模に応じて、適切な方法を選択することが重要であるとのことでした!

いいなと思ったら応援しよう!