pandas の集計機能は SQL の GROUP BY に似ていますが、より柔軟です。「銘柄ごと」「月ごと」「曜日ごと」のような切り口でデータを束ねて、平均・合計・標準偏差などの統計量を一気に算出できます。
本記事では、groupby / agg / pivot_table の 3 つを軸に、株価データに対する典型的な集計パターンを順に確認します。
目次
- インストール
- サンプルデータの準備
- groupby の基本
- agg で複数の集計を同時に
- transform で「グループ集計値を行に戻す」
- 月次・週次に集計する
- pivot_table でクロス集計
- groupby と並べ替えの注意点
インストール
pip install pandas検証バージョン: Python 3.12.5 / pandas 2.2.3
サンプルデータの準備
複数銘柄・複数日のサンプルデータを作ります。
import pandas as pd
data = { "Date": [ "2026-04-01", "2026-04-02", "2026-04-03", "2026-04-04", "2026-04-05", "2026-04-01", "2026-04-02", "2026-04-03", "2026-04-04", "2026-04-05", "2026-04-01", "2026-04-02", "2026-04-03", "2026-04-04", "2026-04-05", ], "Code": [ 7203, 7203, 7203, 7203, 7203, 9984, 9984, 9984, 9984, 9984, 8306, 8306, 8306, 8306, 8306, ], "C": [ 2900, 2925, 2880, 2910, 2945, 9800, 9750, 9900, 9850, 9820, 1450, 1448, 1462, 1470, 1480, ], "Vo": [ 11_000_000, 9_500_000, 12_500_000, 10_200_000, 9_800_000, 4_200_000, 5_100_000, 4_800_000, 3_900_000, 4_400_000, 18_000_000, 17_500_000, 19_200_000, 18_800_000, 17_900_000, ],}df = pd.DataFrame(data)df["Date"] = pd.to_datetime(df["Date"])print(df.head())Date は datetime 型に変換しておきます。後段の月次集計で必要になります。
groupby の基本
「銘柄ごとの平均終値」を計算します。
mean_close = df.groupby("Code")["C"].mean()print(mean_close)Code7203 2912.08306 1462.09984 9824.0Name: C, dtype: float64groupby("Code") で「Code 列の値が同じ行」をグループにまとめ、["C"] で対象列を絞り、.mean() で集計します。「分けて → 計算 → 戻す」が groupby の基本パターンです。
複数列をまとめて集計したいときは、列を選ばずに集計関数を呼びます。
grouped = df.groupby("Code")[["C", "Vo"]].mean()print(grouped)agg で複数の集計を同時に
1 つの列に対して複数の統計量を、列ごとに違う関数を、まとめて指定できます。
summary = df.groupby("Code").agg( mean_close=("C", "mean"), max_close=("C", "max"), min_close=("C", "min"), sum_volume=("Vo", "sum"),)print(summary) mean_close max_close min_close sum_volumeCode7203 2912.0 2945 2880 530000008306 1462.0 1480 1448 914000009984 9824.0 9900 9750 22400000新しい列名=("対象列", "集計関数") の形式が pandas 1.0 系以降の推奨書式です。可読性が高く、どの列がどの集計か一目で分かります。
集計関数には文字列だけでなく、自作のラムダや関数も渡せます。
def range_(s): return s.max() - s.min()
stats = df.groupby("Code").agg( daily_range=("C", range_), std_close=("C", lambda s: s.std(ddof=1)),)print(stats)transform で「グループ集計値を行に戻す」
groupby().mean() は行数が減りますが、transform を使うと 元の行数を保ったまま グループの集計値を各行に貼り付けられます。
df["mean_close_by_ticker"] = df.groupby("Code")["C"].transform("mean")df["close_dev"] = df["C"] - df["mean_close_by_ticker"]print(df.head())「銘柄平均からの乖離」「銘柄ごとの累積リターン」のように、行ごとの計算で集計値が必要な場面で使います。
月次・週次に集計する
日付列をインデックスにして resample を使うと、時間軸での再集計ができます。
df_indexed = df.set_index("Date")monthly = ( df_indexed.groupby("Code")["C"] .resample("ME") .mean())print(monthly)"ME" は月末(Month End)、"W" は週末、"D" は日次です。サンプルでは 1 ヶ月分しかないため値は 1 行ずつですが、長期データで威力を発揮します。時系列の詳細は#4-4「pandas で時系列を扱う」 で扱います。
pivot_table でクロス集計
pivot_table は「行」「列」「値」の 3 軸でクロス集計を作ります。Excel のピボットテーブルと同じ発想です。
pv = df.pivot_table( index="Date", columns="Code", values="C", aggfunc="mean",)print(pv)Code 7203 8306 9984Date2026-04-01 2900.0 1450.0 9800.02026-04-02 2925.0 1448.0 9750.02026-04-03 2880.0 1462.0 9900.02026-04-04 2910.0 1470.0 9850.02026-04-05 2945.0 1480.0 9820.0「銘柄を列に展開した日次価格表」になります。これは ワイド形式 と呼ばれ、銘柄間の相関や複数銘柄チャートを描くときに使いやすい形です。
逆方向(ワイド → ロング)への変換は pd.melt です。#4-5「pandas でデータを結合する」 で扱います。
groupby と並べ替えの注意点
groupby はデフォルトでグループキーをソートします。順序を保ちたいときは sort=False を指定します。
df.groupby("Code", sort=False)["C"].mean()また、グループキーを インデックスに含めたくない ときは as_index=False を使うと、結果が通常の DataFrame になります。
df.groupby("Code", as_index=False)["C"].mean()生成AI へのプロンプト例
集計の意図を生成AI に伝えるときは、入力列・集計軸・出力形式を明確に書きます。
pandas DataFrame に対して次の集計を行うコードを書いてください。
入力:- df(列: Date, Code, C, Vo)- Date は datetime64
要件:- 銘柄ごとに次の値を計算する - 期間中の単純リターン(末日 / 初日 - 1) - 期間中の標準偏差(ddof=1) - 期間中の最大ドローダウン(累積リターンの高値からの最大下落率)- 結果は Code をインデックスに持つ DataFrame- pandas 2.2 系で、agg と transform を使い分ける「列名」「型」「集計の定義」を順に書くと、再現性のあるコードが返ります。
まとめ
groupby + aggで「銘柄ごと・期間ごと」の集計を 1 行で書けるagg(新列名=("元列", "関数"))は推奨書式で可読性が高いtransformは集計値を 各行に戻す 操作で、乖離・標準化に便利pivot_tableでロング形式 → ワイド形式のクロス集計ができる- 月次・週次への再集計は
resampleを使う(時系列は#4-4「pandas で時系列を扱う」)