K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

数値カラムを一括集計する

01.2.3

数値カラムを一括集計する

最終更新 2024-06-01 読了時間 4 分
まとめ
DataFrame.agg は、「平均・中央値・標準偏差」のような複数の集計関数を名前のリストで渡すと、全列に対して一度に計算して 1 枚の表にする関数です。このページでは総務省の歳出データ soumu-gdp-clean.csv の年度列すべてに agg(["count", "mean", "median", "std", "min", "max"]) を適用して転置し、apply で独自関数の変動係数 CV(標準偏差 ÷ 平均)を列として足します。続けて melt で long 形式にしたデータを groupby("カテゴリ").agg(latest=..., avg=..., y1_y10=...) に渡し、費目ごとの最新値・平均・最初と最後の差を 1 行にまとめます。最後に to_markdown でレポート用の表を書き出し、seaborn の lineplot で推移を確かめるところまでを、定例レポートのテンプレートとして組み立てます。

狙い #

定例レポートや監視では「平均・中央値・標準偏差・前年比差分」など複数の指標を一括で計算したい場面が多いです。df["H1"].mean()、df["H1"].median() と列ごと・指標ごとに書くと 30 列 × 6 指標で 180 行のコードになりますが、agg に関数名のリストを渡せば 1 回で全部の組み合わせが埋まります。pandas の agg / describe / groupby を組み合わせると、集計表をテンプレ化できます。

次のコードは整形済み CSV を読み込み、「カテゴリ」以外の列名を数値列として取り出します。

1
2
3
4
import pandas as pd

df = pd.read_csv("../data/processed/soumu-gdp-clean.csv")
value_cols = df.columns.drop("カテゴリ")

1. agg で複数集計 #

次のコードは、年度列すべてに 6 つの統計量を一括で計算し、転置して「1 行 = 1 列の統計量」の表にします。

1
2
3
4
5
6
summary = (
    df[value_cols]
    .agg(["count", "mean", "median", "std", "min", "max"])
    .T.round(2)
)
summary.head()

KPI を追加 #

次のコードは、変動係数 CV(標準偏差 ÷ 平均)を独自関数として定義し、年度ごとの値を summary に列として足して、ばらつきの大きい順に表示します。

1
2
3
4
5
def cv(x):
    return x.std() / x.mean()

summary["cv"] = df[value_cols].apply(cv)
summary.sort_values("cv", ascending=False).head()

独自関数を apply で渡すだけでカスタム KPI も一覧化できます。


2. groupby + agg でカテゴリ別集計 #

次のコードは、wide の表を melt で long にしてからカテゴリごとにまとめ、最新値・平均・最初と最後の差の 3 つを名前付きで集計します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
agg_by_category = (
    df.melt(id_vars="カテゴリ", var_name="year", value_name="value")
      .assign(period=lambda x: x["year"].str.extract(r"([HR]\d+)"))
      .groupby(["カテゴリ"])
      .agg(
          latest = ("value", "last"),
          avg    = ("value", "mean"),
          y1_y10 = ("value", lambda s: s.iloc[-1] - s.iloc[0])
      )
      .round(2)
)
agg_by_category.head()

agg では (列名, 集計関数) のタプルで任意の集計を組み合わせられます。lambda を使えば差分や比率なども一発で算出できます。


3. Aggregation Report を DataFrame にまとめる #

次のコードは、summary に「どの集計か」を表すラベル列を足し、レポートに載せる列だけを選んだ report を作ります。

1
2
3
4
5
6
7
report = (
    summary
    .assign(metric="overall", column=summary.index)
    .reset_index(drop=True)
    .loc[:, ["metric", "column", "mean", "median", "std", "cv"]]
)
report.head()

この report を CSV / Markdown に書き出しておくと、タスク管理ツールや BI へ反映しやすくなります。次の 1 行で Markdown の表として保存します。

1
report.to_markdown("../reports/numerical-summary.md", index=False)

可視化でトレンド確認 #

次のコードは、long 形式のデータをカテゴリごとに色分けした折れ線で描き、年度の推移を確かめます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import seaborn as sns
import matplotlib.pyplot as plt

tidy = df.melt(id_vars="カテゴリ", var_name="year", value_name="value")

plt.figure(figsize=(12, 4))
sns.lineplot(
    data=tidy,
    x="year",
    y="value",
    hue="カテゴリ",
    palette="tab10"
)
plt.xticks(rotation=45)
plt.grid(alpha=.3)
plt.tight_layout()

agg で概況を掴んだあとに、ラインチャートでトレンドを確かめると精度の高いインサイトにつながります。確かめたいのは、agg_by_category の y1_y10 が大きい費目が図でも右上がりの線になっているか、の 1 点です。


チェックリスト #

最初に確認したいのは、agg の結果をテンプレ DataFrame(report)にまとめ、to_markdown でレポート出力を自動化したかです。二つ目はカスタム KPI(CV、前年比差分など)も apply や lambda で定義したか、三つ目は groupby と組み合わせてカテゴリ別の増減(y1_y10)を lineplot で可視化できる状態にしたかです。最後に Markdown / CSV 出力を整備し、ナレッジ共有しやすくしたかを見ます。

このテンプレートを他プロジェクトでも再利用できるよう GitHub gist や Snippet 管理に登録しておくと便利です。