pandas で SQL を使う

Prep

pandas で SQL を使う

SQL の既存知識を活かしたい場合、pandas で整形した DataFrame を SQLite に載せ替えて SELECTJOIN を実行するのが手っ取り早いです。ここでは in-memory DB を使った最小構成を紹介します。

import pandas as pd
from sqlite3 import connect

df = pd.read_csv("../data/processed/soumu-gdp-clean.csv")
df.columns = df.columns.str.replace("年度", "")

1. DataFrame → SQLite #

conn = connect(":memory:")  # メモリ上の SQLite
df.to_sql("gdp", conn, index=False, if_exists="replace")
  • :memory: を使うと一時的に DB を作成
  • if_exists="replace" で再実行時も上書きできる
  • 列名にスペースがある場合は df.columns = df.columns.str.replace(" ", "_") などで事前に正規化

2. SQL を実行 (read_sql) #

query = """
SELECT
  カテゴリ,
  R1 - H1 AS diff_recent,
  AVG(H1) AS avg_h1
FROM gdp
WHERE (R1 - H1) > 5
ORDER BY diff_recent DESC
"""

result = pd.read_sql(query, conn)
result.head()

read_sql に文字列を渡すだけで DataFrame が返ってくるため、SQL と pandas を行き来しながら探索できます。


3. pandas + SQL ハイブリッド #

サブクエリで Year 列を UNPIVOT #

years = [col for col in df.columns if col.startswith(("H", "R"))]
year_select = " + ".join([f"SUM({y}) AS {y}" for y in years])

SQLite は標準の UNPIVOT を持たないため、以下のように pandas の melt を使った結果を SQL に登録すると便利です。

tidy = df.melt(id_vars="カテゴリ", var_name="year", value_name="value")
tidy.to_sql("gdp_tidy", conn, index=False, if_exists="replace")

pd.read_sql(
    """
    SELECT year, AVG(value) AS avg_value
    FROM gdp_tidy
    GROUP BY year
    ORDER BY year
    """,
    conn
)

4. 逆方向:SQL → pandas #

データベースにあるテーブルを pandas に持ってくるときは read_sql_table / read_sql_query を使います。

import sqlalchemy as sa

engine = sa.create_engine("sqlite:///../data/warehouse.db")
df_from_db = pd.read_sql_table("fact_sales", con=engine)

SQLAlchemy を用いると PostgreSQL や BigQuery など他エンジンにも同じ要領で接続できます。


運用 Tips #

  1. SQL を資産として残す
    Notebook のセルに貼り付けるだけでなく、queries/ ディレクトリに .sql ファイルとして保存しておくとレビューしやすい。

  2. ビューの代わりに pandas パイプライン
    df.pipe(...) でフィルタや集計を関数化しておき、SQL で取得した直後に適用する。

  3. 大規模データへの拡張
    測定目的なら SQLite で、実運用なら DuckDB や Polars など列志向エンジンも検討する。


チェックリスト #

  • DataFrame を to_sql で DB 化し、read_sql で往復するテンプレを持った
  • 列名・型を SQL 向けに正規化してから投入した
  • Notebook とは別に .sql ファイルを保管し、再利用できるようにした
  • pandas の melt/pivot と SQL の集計を組み合わせ、得意な言語からアプローチできるようにした
  • 将来のデータ量増加に備えて、SQLite → DuckDB / DWH への移行経路を検討した

これで「既存の SQL クエリを pandas 上でも即座に再現する」ための土台が整いました。