はじめに
Polars は SQL との連携をサポートしていますが、より読みやすく表現力のあるコードを書くためには、 エクスプレッション構文 に慣れることをお勧めします。 DataFrame インターフェースが Polars の主要機能であるため、新機能は通常まずエクスプレッション API に追加されます。 しかし、既存の SQL コードベースを持っているユーザーや SQL の使用を好むユーザー向けに、Polars は SQL をサポートしています。
Note
Polars には固有の SQL エンジンはありません。なぜなら Polars は SQL クエリを エクスプレッション に変換し、独自のエンジンを使って実行するためです。このアプローチにより、純粋な DataFrame ライブラリとしての Polars のパフォーマンスとスケーラビリティの利点を維持しつつ、SQL を使用する機能を提供しています。
コンテキスト
Polars は SQL クエリを管理するために SQLContext
オブジェクトを使用します。このコンテキストには、DataFrame
と LazyFrame
の識別子名とそれに対応するデータセット 1 のマッピングが含まれます。以下の例では SQLContext
を開始しています:
ctx = pl.SQLContext()
DataFrameの登録
SQLContext
の初期化時に DataFrame を登録する方法はいくつかあります。
- グローバル名前空間内のすべての
LazyFrame
およびDataFrame
オブジェクトを登録する方法 - 辞書マッピングまたは kwargs を使って明示的に登録する方法
df = pl.DataFrame({"a": [1, 2, 3]})
lf = pl.LazyFrame({"b": [4, 5, 6]})
# Register all dataframes in the global namespace: registers both "df" and "lf"
ctx = pl.SQLContext(register_globals=True)
# Register an explicit mapping of identifier name to frame
ctx = pl.SQLContext(frames={"table_one": df, "table_two": lf})
# Register frames using kwargs; dataframe df as "df" and lazyframe lf as "lf"
ctx = pl.SQLContext(df=df, lf=lf)
Pandas DataFrame も、Polars に変換することで登録できます。
import pandas as pd
df_pandas = pd.DataFrame({"c": [7, 8, 9]})
ctx = pl.SQLContext(df_pandas=pl.from_pandas(df_pandas))
Note
Numpy をバックエンドとして使用している Pandas DataFrame を変換すると、変換のコストが高くなる可能性があります。しかし、Arrow をバックエンドとして使用している場合、変換のコストを大幅に抑えることができます (場合によってはほぼゼロに近くなります)。
SQLContext
が初期化されたら、以下の方法で追加の DataFrame を登録したり、既存の DataFrame を登録解除できます:
register
register_globals
register_many
unregister
クエリの実行と結果の収集
SQL クエリは、クエリ計画の最適化を最大限に活用するために、常に遅延モードで実行されます。 そのため、結果を収集するには2つの方法があります:
SQLContext
のeager_execution
パラメーターを True に設定してください。これにより Polars はexecute
呼び出しから LazyFrame の結果を自動的に収集するようになります。execute
でクエリを実行する際にeager
パラメーターを True に設定するか、collect
を使用して明示的に結果を収集してください。
SQL クエリは SQLContext
の execute
を呼び出して実行します。
# For local files use scan_csv instead
pokemon = pl.read_csv(
"https://gist.githubusercontent.com/ritchie46/cac6b337ea52281aa23c049250a4ff03/raw/89a957ff3919d90e6ef2d34235e6bf22304f3366/pokemon.csv"
)
with pl.SQLContext(register_globals=True, eager_execution=True) as ctx:
df_small = ctx.execute("SELECT * from pokemon LIMIT 5")
print(df_small)
shape: (5, 13)
┌─────┬───────────────────────┬────────┬────────┬───┬─────────┬───────┬────────────┬───────────┐
│ # ┆ Name ┆ Type 1 ┆ Type 2 ┆ … ┆ Sp. Def ┆ Speed ┆ Generation ┆ Legendary │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ str ┆ str ┆ ┆ i64 ┆ i64 ┆ i64 ┆ bool │
╞═════╪═══════════════════════╪════════╪════════╪═══╪═════════╪═══════╪════════════╪═══════════╡
│ 1 ┆ Bulbasaur ┆ Grass ┆ Poison ┆ … ┆ 65 ┆ 45 ┆ 1 ┆ false │
│ 2 ┆ Ivysaur ┆ Grass ┆ Poison ┆ … ┆ 80 ┆ 60 ┆ 1 ┆ false │
│ 3 ┆ Venusaur ┆ Grass ┆ Poison ┆ … ┆ 100 ┆ 80 ┆ 1 ┆ false │
│ 3 ┆ VenusaurMega Venusaur ┆ Grass ┆ Poison ┆ … ┆ 120 ┆ 80 ┆ 1 ┆ false │
│ 4 ┆ Charmander ┆ Fire ┆ null ┆ … ┆ 50 ┆ 65 ┆ 1 ┆ false │
└─────┴───────────────────────┴────────┴────────┴───┴─────────┴───────┴────────────┴───────────┘
複数のソースからのクエリ実行
同様に、複数のソースから SQL クエリを実行することも簡単にできます。 以下の例では、次のものを登録しています:
- CSV ファイル (遅延読み込み)
- NDJSON ファイル (遅延読み込み)
- Pandas DataFrame
そして SQL を使って、これらを結合します。 遅延読み込みを使用すると、ファイルから必要な行と列のみを読み込むことができます。
同様に、クラウドのデータレイク(S3, Azure Data Lake)を登録することもできます。
PyArrow データセットがデータレイクを指すようにし、scan_pyarrow_dataset
を使って Polars で読み込むことができます。
# Input data:
# products_masterdata.csv with schema {'product_id': Int64, 'product_name': String}
# products_categories.json with schema {'product_id': Int64, 'category': String}
# sales_data is a Pandas DataFrame with schema {'product_id': Int64, 'sales': Int64}
with pl.SQLContext(
products_masterdata=pl.scan_csv("docs/data/products_masterdata.csv"),
products_categories=pl.scan_ndjson("docs/data/products_categories.json"),
sales_data=pl.from_pandas(sales_data),
eager_execution=True,
) as ctx:
query = """
SELECT
product_id,
product_name,
category,
sales
FROM
products_masterdata
LEFT JOIN products_categories USING (product_id)
LEFT JOIN sales_data USING (product_id)
"""
print(ctx.execute(query))
shape: (5, 4)
┌────────────┬──────────────┬────────────┬───────┐
│ product_id ┆ product_name ┆ category ┆ sales │
│ --- ┆ --- ┆ --- ┆ --- │
│ i64 ┆ str ┆ str ┆ i64 │
╞════════════╪══════════════╪════════════╪═══════╡
│ 1 ┆ Product A ┆ Category 1 ┆ 100 │
│ 2 ┆ Product B ┆ Category 1 ┆ 200 │
│ 3 ┆ Product C ┆ Category 2 ┆ 150 │
│ 4 ┆ Product D ┆ Category 2 ┆ 250 │
│ 5 ┆ Product E ┆ Category 3 ┆ 300 │
└────────────┴──────────────┴────────────┴───────┘
互換性
Polars は SQL 仕様全体をサポートしているわけではありませんが、最も一般的なステートメントタイプのサブセットをサポートしています。
Note
可能な限り、Polars は PostgreSQL の構文定義と関数の動作に従うことを目指しています。
例えば、サポートされている機能の一部は以下の通りです:
CREATE
ステートメント:CREATE TABLE xxx AS ...
SELECT
ステートメント:WHERE
、ORDER
、LIMIT
、GROUP BY
、UNION
、JOIN
句など- 共通テーブル式 (CTE) :
WITH tablename AS
など - クエリを説明する:
EXPLAIN SELECT ...
- 登録済みのテーブルを一覧表示する:
SHOW TABLES
- テーブルを削除する:
DROP TABLE tablename
- テーブルを空にする:
TRUNCATE TABLE tablename
以下は、まだサポートされていない機能の一部です:
INSERT
、UPDATE
、DELETE
ステートメントANALYZE
などのメタクエリ
今後のセクションでは、各ステートメントについてより詳しく説明します。
-
加えて、共通テーブルエクスプレッション も管理します。 ↩