polars について
polarsは、Polars Pythonライブラリを使う開発者や分析担当者向けのデータ処理スキルです。遅延クエリを組み立てて`.collect()`でまとめて実行する方針を取り、スキーマ確認、結果検証、SQL、APIの注意点も扱います。
主な機能
- 01遅延APIでクエリを構築
- 02クエリ前にスキーマを確認
- 03Python UDFよりネイティブ式を優先
- 04早期フィルターと結果検証
- 05遅延エンジンでSQLを使用
- 06API詳細とよくある注意点の確認
活用シーン
- 01CSVやParquetデータに関する質問への回答
- 02pandasの処理をPolarsへ移行
- 03PolarsでSQLクエリを作成
- 04結合、null、式に関するエラーの回避
MCP 対応
利用可能な場合、`polars-mcp`サーバーのツールでPolars APIドキュメントを検索、閲覧、取得するよう案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ polars-inc/ skills --skill polarsインストール後、Claude Code で/polarsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/contexts.mdexpressions.mdinsight-recipes.mdlazy-api.mdpandas-to-polars.mdsql.md詳細
Polars
基本方針
データ処理には Polars を使用します。常に遅延 API を使用します。クエリ全体を組み立ててから、.collect() を 1 回呼び出して実行することで、Polars はデータを読み込む前にプランを最適化できます。.collect() はストリーミングエンジンで実行され、データをバッチ単位で処理してメモリへの負荷を軽減します。中間結果を収集しないでください。.collect() を呼び出すたびにデータが実体化され、プランが破棄されるため、その後の処理はすべて最初から最適化されます。イーガーなコードはオプティマイザーをスキップし、より多くの処理を行います。
すでにメモリ上にあるデータも例外ではありません。 クエリの開始点が DataFrame(関数の引数、pl.from_pandas(pdf)、pl.DataFrame(...)、または先行する collect() の結果)の場合は、最初の操作の前に .lazy() を呼び出し、最後に .collect() を呼び出します。.lazy() はコストがかかりません(データをラップするだけで、コピーはしません)。また、段階的なイーガーパイプラインを最適化された 1 つのプランに変えるために必要です。ユーザーがイーガー実行を求めている場合を除き、これを行ってください。
# start from a file
pl.scan_csv("data.csv").filter(...).collect()
# start from an existing DataFrame — wrap it first
df.lazy().filter(...).group_by(...).agg(...).collect()
# avoid: eager, step by step, nothing to optimize
df = pl.read_csv("data.csv")
df.filter(...).group_by(...).agg(...)
質問からインサイトへ
ユーザーがデータについての質問(「前四半期に最も成長した地域はどこですか?」など)をした場合、目指すのは一度で正確な回答を出すことです。スキーマの確認に低コストのステップを 1 回使い、その後、クエリ全体を一度で記述します。まず references/insight-recipes.md を読んでください。top-k、期間ごとの比較、分布、時系列、コホート形式の質問に対応する、すぐに使えるクエリパターンと、回答前に実行する健全性チェックが記載されています。
- 最初にスキーマを確認します。列名やデータ型を推測してはいけません。
lf = pl.scan_csv("sales.csv") # or scan_parquet / scan_ndjson
print(lf.collect_schema()) # names and dtypes, no data read
print(lf.head(5).collect()) # eyeball values, formats, dirt
- 質問を、以下の標準パターンに従う 1 つの遅延チェーンに変換します。 曖昧な用語は明確な定義に置き換え、回答の中で明示します(「成長率 = 前四半期比の売上高、パーセント」)。
- 汚れたデータはスキャン時に処理し、後続処理に持ち込まないようにします。
pl.scan_csv(path, null_values=["N/A", ""], try_parse_dates=True)。 - 回答する前に、結果の妥当性を確認します。
- コードだけでなく、数値で回答します。 インサイトを最初に示し、根拠となるテーブルを提示します。また、追加の質問でチェーンを拡張できるように、LazyFrame は保持しておき、作り直さないようにします。
基本ルール
- Python 関数より式を使用します。 式で実現できない場合に限り、
map_elements、map_batches、map_groupsを使用します。ほとんどの場合、式で実現できます。式は Rust で並列実行されますが、Python UDF はすべての値をインタープリター経由で処理するため、最適化が無効になります。 - 早い段階でフィルターを適用します。 後続の各ステップを通過するデータ量を減らすため、
filter()はgroup_by()、join()、with_columns()より前に配置します。 - 1 つのコンテキストにつき、各操作に式を 1 つ使用します。 すべての式を 1 つの
with_columns()に渡します。同じコンテキスト内の式は並列実行されますが、ループ内で呼び出しを繰り返すと直列化されます。同じ操作を複数の列に適用する場合は、列ごとに式を書くのではなく、スキーマ全体に展開する 1 つの式を記述します。展開された列の名前は.name.suffix()/.name.prefix()で変更します。.alias()が名前を付けるのは 1 つの出力だけです。セレクターの形式と注意事項についてはreferences/expressions.mdを参照してください。 - Polars は厳密な型付けを行います。 暗黙の型変換はなく、列内に複数の型を混在させることもできません。
.cast()で明示的に型変換します。変換できない値をエラーではなく null にするには、.cast(pl.Float64, strict=False)を使用します。文字列を日付や日時に変換する場合は、.cast()ではなくstr.to_date()/str.to_datetime()を使用します。 - 警告を尊重し、決して無視しないでください。 Polars の警告メッセージには、具体的な修正方法が記載されています。
PerformanceWarningやPolarsInefficientMapWarningなどのサブクラスは、collect_schema()の使用や、map_elements呼び出しをネイティブ式に書き換えることを指示しています。変更を適用し、警告を隠すためにwarnings.filterwarnings("ignore")やwarnings.catch_warnings()を使用してはいけません。
import polars.selectors as cs
# avoid: same operation, one expression per column
lf.with_columns([(pl.col(c) * 1.1).alias(f"{c}_adj") for c in ["a", "b", "c"]])
# prefer: one expression, expanded by the schema
lf.with_columns((pl.col("a", "b", "c") * 1.1).name.suffix("_adj"))
lf.with_columns(cs.numeric().fill_null(0)) # in place, same names
標準的なクエリパターン
クエリは以下の順序で組み立てます。各ステップで、次のステップの前にデータ量を減らします。
customers = pl.scan_csv("customers.csv")
result = (
pl.scan_csv("orders.csv") # 1. scan, never read
.filter(pl.col("year") == 2024) # 2. filter early
.join(customers, on="customer_id", how="left") # 3. join filtered data
.with_columns( # 4. add computed columns
(pl.col("revenue") - pl.col("cost")).alias("profit")
)
.group_by("region") # 5. group
.agg( # 6. aggregate
pl.col("profit").sum().alias("total_profit"),
pl.col("profit").mean().alias("avg_profit"),
pl.len().alias("count"),
)
.filter(pl.col("count") > 10) # 7. filter groups
.sort("total_profit", descending=True) # 8. sort
.select("region", "total_profit", "avg_profit") # 9. final columns
.collect() # 10. execute once
)
SQL
Polars は SQL も実行できます。pl.sql(...)、lf.sql(...)、pl.SQLContext は同じ遅延エンジン上で動作し、同じ最適化済みプランにコンパイルされます。ユーザーが SQL を書く場合や SQL を求める場合、または SQL クエリを移植する場合に使用してください。それ以外では式を記述します。エントリポイントといくつかの方言の違いについては、記述する前に references/sql.md を読んでください。
注意点
以下はいずれも間違えやすい点です。
then()/otherwise()内の文字列は値ではなく列名です。pl.when(c).then("adult")はadultという列を読み込みます(またはColumnNotFoundErrorが発生します)。リテラルは.then(pl.lit("adult"))のようにラップしてください。- null の比較では、行が暗黙に除外されます。
filter(pl.col("v") > 2)は、null > 2が null となり、偽として扱われるため、null を除外します。null を残す場合は、(pl.col("v") > 2) | (pl.col("v").is_null())とします。 - 各条件を括弧で囲み、
&、|、~を使用してください。 Python のand/or/notは式に対して使うとエラーになり、括弧がないと演算子の優先順位によって比較が誤って結び付けられます。(pl.col("a") > 1) & (pl.col("b") < 5)。 with_columns()内で集約だけを指定すると、全体の値がすべての行にブロードキャストされます。with_columns(pl.col("v").mean())は列全体を平均値で埋めます。エラーにはなりません。各行に対応するグループごとの値を取得するには、.over("group")を追加してください。- 出力名が重複すると
DuplicateErrorが発生します。 計算列は元の列名を引き継ぐため、select(pl.col("p"), pl.col("p") * 1.1)は失敗します。派生列には必ず.alias()を使用してください。展開された式には.name.suffix(...)を使用すると、すべての元の列名が保持されます。 - 正規表現による列選択には
^...$アンカーが必要です。pl.col("sales_.*")はリテラルの列名として解釈され、ColumnNotFoundErrorが発生します。pl.col("^sales_.*$")は列名に展開されます。1 回のcol()呼び出しで列名と dtype を混在させることはできません。代わりにセレクターを使用してください。 - デフォルトでは、結合時に null は一致しません。 null キーを持つ行は内部結合で暗黙に除外されます。一致させる場合は
nulls_equal=Trueを渡してください。 - 結合とグループ化では、行の順序は保持されません。 結果の順序が重要な場合は最後に
.sort()を付けるか、join(..., maintain_order="left")を渡して左側の DataFrame の順序を保持してください。
バージョンと API の確認
確信のないメソッド呼び出しを記述する前に、記憶に頼らず、インストール済みのバージョンで確認してください。Polars に pandas と同じ表記があると決めつけないでください。インデックス、iloc、groupby はありません。Polars 1.x では、まず references/lazy-api.md の末尾にある「On Polars 1.x」のセクションを読んでください。
polars-mcpサーバーのツールを利用できる場合は、それらを使用してください。polars_search_api("filter")はキーワードでメソッドを検索し、polars_browse("Expr.str")は名前空間を確認し、polars_get_docstring("Expr.str.contains")は正確なシグネチャを取得します。- それ以外の場合はドキュメントを取得してください。
references/expressions.mdの冒頭には、各式カテゴリに対応する https://docs.pola.rs 上の最新 URL が記載されています。
リファレンスを読み込むタイミング
これらのリファレンスファイルには、このファイルに記載されていない詳細が含まれています。以下の項目に該当するタスクでは、コードを書く前に必ず該当するリファレンスを読んでください。リファレンスに記載がある内容について、記憶だけで翻訳したり回答したりしないでください。各ファイルの冒頭には、該当セクションに移動するための ## Contents 行があります。
- pandas から Polars への変換 — まず
references/pandas-to-polars.mdを必ず読んでください(短いファイルです)。このファイルに記載されていない、API の差異に関する注意点が含まれています。 - 自然言語によるデータの質問への回答 —
references/insight-recipes.md(上記の「質問からインサイトへ」を参照)。 references/contexts.md—select、with_columns、filter、group_by/agg、over(ウィンドウのマッピング戦略)、sort、joinの詳しい動作。references/expressions.md— 文字列、日時、リスト、構造体、展開、 セレクターの構文、型変換、null の処理、条件式、および 上記のフェッチマップ。references/lazy-api.md— 汚れたデータ向けのスキャンオプション、explain()によるクエリプランの確認、 メモリに収まらない大規模データとシンク(sink_parquet)、および Polars 1.x における違い。references/sql.md— SQL のエントリーポイント、SQL と式の併用、方言に関する注意点、 および SQL リファレンスのフェッチマップ。