🔖 キーワード索引
本ページのトピックを 1 タップで移動できます。 「集約(aggregation)」— 日本語では「集計」とも呼ばれ、本ページでは同義語として両方の表記を用いる — を学ぶうえで押さえたい論点はすべてここに集約しました。
「aggregation 」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「aggregation」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。
aggregation 統計分析 SSDSE-B-2026 前提条件 適用範囲 落とし穴 関連手法 Python 実装 検証方法
これらのキーワードは「aggregation の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。
💡 30秒で分かる結論
🍰 まずはやさしく
バラバラのデータを束ねる作業です。
データの全体像をパッと見るために使います。
部活のメンバーを学年ごとに分けるようなものです。
集約のやり方と注意点を学びます。
複数行のデータを groupby などのキーで束ね 、 合計・平均・件数などの要約統計量に変換する操作。
定義 :複数行のデータを groupby などのキーで束ね、 合計・平均・件数などの 要約統計量 に変換する操作。SSDSE-B-2026 での例 :47 都道府県を 地方ブロック(北海道・東北・関東…) でグループ化し、 人口・出生数・大学数の合計や平均を算出。核となる関数 :pandas では df.groupby(key).agg(...) が中心。 SQL でいう GROUP BY と完全に対応。注意 :集計後は 行数が必ず減る 。 元データに戻れない情報(個別の都道府県値・分散)を取り違えないこと。分野 :データ処理 — 📚 データエンジニアリング / データクレンジング 。関連手法 :ピボットテーブル 、 内部結合 、 データ結合 、 縦持ち・横持ち変換 。
📍 あなたが今見ているもの
🍰 まずはやさしく
分析の準備をするためのステップです。
データを使いやすい形に変えるために使います。
スマホのアプリで、日ごとの利用時間をまとめる時に似ています。
分析の流れの中でどこに位置するかを学びます。
分野 :データエンジニアリング(前処理 → 集計 → 可視化 → モデル化のうち、 集計フェーズ)。 SSDSE-B-2026 のような 個票形式の都道府県データ を分析する第一歩。
位置づけ :個票(個別観測)レベルから 分析単位 (地方ブロック・年齢階級・職業大分類など)への変換。 探索的データ分析(EDA)の最初の山場。
典型的なワークフロー :CSV 読み込み → 列名整理 → 型変換 → 集計 → 可視化 / モデル化。 集計の出力が、 後続のすべての作業の入力になる。
関連 :groupby / ピボットテーブル / 結合(join) と組み合わせて使う。
🎨 直感で掴む
🍰 まずはやさしく
家計簿の月締めのような作業です。
細かい数字をまとめて、傾向をつかむために使います。
1日ごとの買い物記録を、食費などの項目でまとめることです。
合計や平均など、まとめ方の種類について学びます。
「集計」とは、 たくさんある行を意味のあるまとまりに束ねて、 数値を 1 行に要約する こと。 たとえば SSDSE-B-2026 には 12 年度(2012〜2023)× 47 都道府県 × 約 110 列(人口・出生・教育 等)が並んでいる。 これを「地方ブロックごとの合計人口は?」「東日本 vs 西日本で大学数の平均はどちらが大きい?」と問うとき、 私たちは 都道府県 47 行 → 地方ブロック 8 行 に 行数を圧縮 している。 これが集計の本質。
日常生活の比喩でいえば、 集計は 「家計簿の月締め」 に近い。 1 日ごとのレシート(個票)を、 「食費」「交通費」のカテゴリで縦に積み上げて月別合計に変換する。 元のレシート 1 枚 1 枚は残らないが、 全体傾向が見える。 同じように、 SSDSE では「47 都道府県の個別値」を 1 枚 1 枚のレシートに見立て、 「地方ブロック」というカテゴリで束ねる。
集計には主に 3 タイプある:
合計型 (sum):人口・出生数のように 絶対量 に意味がある変数。 「関東の総人口」「東北の出生数合計」など。
平均・中央値型 (mean, median):年齢中央値・平均気温のように 水準 を示す変数。 県のサイズに依存しない指標を作りたいときに使う。
件数・割合型 (count, nunique, ratio):「該当する自治体数」「全国シェア」など カウント に意味がある変数。 カテゴリ列の集計で活躍。
大事なのは、 「合計」と「平均」と「件数」で見える物語がまったく違う ということ。 たとえば「関東は人口合計で日本一(2023 年度で 4,353 万人)」だが、 東京都単独(1,409 万人)が突出しているため、 7 都県の「平均人口」(622 万人)は東京単独の半分以下になる。 だから集計関数の選び方が分析の質を決める。
SSDSE-B-2026 を使った具体的な集計例は、 後段「🧮 実値で計算してみる」で扱う。 そこでは 47 都道府県を 8 つの地方ブロックに分けて合計人口・平均高齢化率を計算 する。
歴史的背景 :集計は統計学の起源そのもの。 17 世紀のジョン・グラントが「ロンドン死亡記録」を週次集計したのが近代統計の出発点とされ、 19 世紀のフローレンス・ナイチンゲールも野戦病院の死因を集計してインフォグラフィックを発明した。 つまり集計は 「データを意思決定可能な情報に変える」 最古かつ最強の技法。
🎨 集計結果の可視化 5 パターン
1. 棒グラフ(ランキング)
SSDSE-B-2026 の集計結果を棒グラフで表示。 横棒は項目名が長いとき。 縦棒は時系列で。
2. 箱ひげ図(分布)
地方ブロック内の県のばらつきを箱ひげ図で。 平均だけでなく分布全体を伝える。
3. ヒートマップ(クロス集計)
地方ブロック × 年度のクロス集計をヒートマップで。 色の濃淡で全体傾向。
4. 折れ線(時系列集計)
地方ブロック別の年次推移を折れ線で。 凡例でブロック識別。
5. 円グラフ(シェア)
「全国に対する各地方ブロックのシェア」を円で。 項目が多すぎると見にくいので注意。
📜 集計概念の発展史
1662 年:グラントの『死亡表観察』
ロンドン市の死亡記録を年齢別・死因別に集計 。 近代統計学の起源。
1858 年:ナイチンゲールのローズダイアグラム
クリミア戦争の野戦病院死因を月別・原因別に集計し、 ローズダイアグラムで可視化。
1970 年代:SQL の登場
IBM の Edgar Codd が関係データベース理論を提案。 GROUP BY が標準化。
1990 年代:OLAP の隆盛
多次元集計(CUBE, ROLLUP)が業務分析の標準ツールに。
2010 年代:pandas + Tidy Data
Wickham の Tidy Data 哲学と pandas の groupby が、 「集計を Python で誰でもできる」時代を実現。
2020 年代:Polars / DuckDB
pandas より高速な Polars、 SQL ベースの DuckDB が登場。 巨大データの集計が一般化。
🎨 集計結果の可視化コード集(SSDSE-B-2026)
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口)
北海道 5,092,000
東京都 14,086,000
沖縄県 1,468,000
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 import pandas as pd
# block_map はこのあとのブロックで作っているので、ここでも用意しておく
_pref = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' ,
skiprows = [ 1 ])[ 'Prefecture' ] . unique ()
def _blk ( code_i ):
if code_i == 1 : return '北海道'
if 2 <= code_i <= 7 : return '東北'
if 8 <= code_i <= 14 : return '関東'
if 15 <= code_i <= 23 : return '中部'
if 24 <= code_i <= 30 : return '近畿'
if 31 <= code_i <= 35 : return '中国'
if 36 <= code_i <= 39 : return '四国'
return '九州沖縄'
block_map = { p : _blk ( i + 1 ) for i , p in enumerate ( _pref )}
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ], na_values = [ '-' ])
df [ 'Block' ] = df [ 'Prefecture' ] . map ( block_map )
y2023 = df [ df [ 'SSDSE-B-2026' ] == 2023 ]
# 1. 棒グラフ
agg = y2023 . groupby ( 'Block' )[ 'A1101' ] . sum () . sort_values ()
agg . plot . barh ( figsize = ( 8 , 6 ))
plt . title ( '地方ブロック別 総人口(2023)' )
plt . savefig ( 'outputs/block_pop.png' )
# 2. 箱ひげ図
plt . figure ( figsize = ( 10 , 6 ))
sns . boxplot ( data = y2023 , x = 'Block' , y = 'A1101' )
plt . title ( '地方ブロック内の都道府県人口分布' )
plt . xticks ( rotation = 45 )
plt . savefig ( 'outputs/block_boxplot.png' )
# 3. ヒートマップ(地方×年)
pv = df . pivot_table ( index = 'Block' , columns = 'SSDSE-B-2026' , values = 'A1101' , aggfunc = 'sum' )
sns . heatmap ( pv , annot = True , fmt = '.0f' , cmap = 'YlOrRd' )
plt . title ( '地方ブロック別 総人口の推移' )
plt . savefig ( 'outputs/block_year_heat.png' )
# 4. 折れ線
df . groupby ([ 'Block' , 'SSDSE-B-2026' ])[ 'A1101' ] . sum () . unstack ( 0 ) . plot ( figsize = ( 10 , 6 ))
plt . title ( '地方ブロック別 総人口の年次推移' )
plt . savefig ( 'outputs/block_year_line.png' )
# 5. 円グラフ
agg . plot . pie ( autopct = ' %1.1f%% ' , figsize = ( 8 , 8 ))
plt . title ( '全国に対する地方ブロック別人口シェア' )
plt . savefig ( 'outputs/block_pie.png' )
🔬 数式を言葉で読み解く
記号 意味
g グループ(地方ブロック・年齢階級など)の識別子。 SSDSE では「地方ブロック」が典型。 S_g グループ g に属する観測(行)の集合。 例:S_関東 = {埼玉, 千葉, 東京, 神奈川, 茨城, 栃木, 群馬} の 7 行。 n_g グループ g のサンプル数(行数)。 SSDSE で都道府県を集計するなら例えば n_関東 = 7。 x_i 個別観測値(県別の人口・出生数など)。 sum(g) グループ g の合計。 SSDSE で「関東の総人口 = sum(g=関東)」のように使う。 mean(g) グループ g の平均。 「関東の平均出生率」など、 県数で正規化された指標。 var(g) グループ内分散。 ばらつきの大きさ。 集計値だけ見ると失われがちな情報。 min/max(g) グループ内最小・最大。 関東なら東京(最大)と栃木(中位)の差で 幅 が見える。 block(i) 行 i がどの地方ブロックに属するかを返す写像。 集計キーの本体。 share(g) グループ g のシェア(%)。 集計値を全体合計で割って 100 倍。 A_{b,s} 2 キー集計(地方ブロック b × 性別 s)の結果。 ピボット表の各セル。
🔬 数式を言葉で読み解く(深掘り)
集計の中心式 $$\text{Aggregate}_k = f(\{x_i : g(x_i) = k\})$$ を 1 記号ずつ 詳細に解読していきます。 単純な記号列に見えますが、 この式には 集計操作の全本質 が圧縮されています。 SSDSE-B-2026 を扱うときは、 この式の意味を常に頭の中で展開しておきましょう。 本セクションは 500 字以上の詳細解説です。
第 1 記号 k(キー) は、 集計後に残るグループの識別子です。 SSDSE-B-2026 で「都道府県を地方ブロックで集計」する場合、 k は「北海道・東北・関東・中部・近畿・中国・四国・九州沖縄」の 8 値を取ります。 k の値域が大きすぎると(例:47 都道府県)集計の効果が薄く、 小さすぎると(例:東日本・西日本の 2 値)情報損失が大きくなります。 「意思決定に必要な粒度 」と「統計的に安定する標本数 」のバランスでキーを選ぶのが、 集計設計の第一歩です。
第 2 記号 g(グループ化関数) は、 個別観測 x_i を集計キー k に対応付ける関数です。 「都道府県 → 地方ブロック」のマッピングが典型例。 g は pandas の df.groupby('Block') の引数 'Block' 列の作成方法に該当します。 ここでよく失敗するのは、 g の定義が暗黙的になってしまう こと。 たとえば「沖縄を九州沖縄に入れるか、 沖縄単独で扱うか」の選択は分析結果に影響します。 g を辞書・関数として明示的に定義し、 git で版管理することが、 再現可能な集計の基本です。
第 3 記号 f(集約関数) は、 同じキー k を持つ個別観測値の集合から 1 つの代表値を計算する関数です。 sum(合計)・mean(平均)・median(中央値)・min・max・count・std などが代表的。 重要なのは「f の選択で結論が反転する 」こと。 SSDSE-B-2026 で「地方ブロックの代表人口」を sum で取れば関東がトップ、 mean で取れば 1 県あたりが大きい関東が依然トップ、 median で取ればばらつきの中央が見えます。 さらに人口で重み付けした加重平均を取れば、 まったく別の数値になります。 「どの f を選んだか」を必ず併記 する習慣をつけましょう。 最後に第 4 記号 {x_i : g(x_i) = k}(条件付き集合) は、 「g(x_i) が k と等しい x_i のみを集めた集合」を意味します。 この記法は集合論の標準。 pandas でいえば df[df['Block']==k] や、 内部的に同じ操作を行う df.groupby('Block').get_group(k) に相当します。 集合のサイズ(|{...}|)が「グループ内サンプル数」となり、 これが少ない(例:5 県未満)と統計的に不安定。 必ず count も同時に確認するのが鉄則です。
🏭 産業事例:集計が事業判断を変えた 6 例
事例 業界 集計が何を明らかにしたか
Amazon の商品分類別売上 EC 数億 SKU の売上を商品分類で集計し、 長尾分布 を発見。 「Long Tail 戦略」の根拠データに。
Walmart の店舗別売上 小売 POS データを店舗・時間帯で集計し、 「雨の日のビールとおむつの相関 」を発見(バスケット分析の祖)。
SSDSE-B-2026 地方ブロック分析 公的統計 47 県を 8 地方ブロックに集計することで、 地域格差 と東京一極集中 が一目瞭然に。
CDC の感染症週次レポート 公衆衛生 米国 50 州 + DC の症例を週次・年齢階級で集計。 流行のピーク・地域差を可視化。
Netflix の視聴時間分布 動画配信 作品×視聴者属性×時間帯で集計し、 「20 時台のドラマ需要 」を発見。 オリジナル制作の優先度判断に。
UN World Happiness Report 国際機関 160 か国の幸福度サーベイを国別・地域別で集計。 「北欧は GDP より幸福度が高い 」と政策発信。
📊 集約関数の詳細比較(10 種類)
関数 pandas 書式 特徴・使う場面
sum .sum()合計。 SSDSE で「地方ブロックの総人口」など。 NaN は 0 として無視。
mean .mean()算術平均。 外れ値の影響大。 SSDSE では加重平均が必要なケース多。
median .median()中央値。 外れ値に頑健。 ばらつきが大きい SSDSE 指標で推奨。
count .count()非欠損値の数。 欠損が多い列で重要。
size .size()グループ内の行数(欠損含む)。 count とは異なる。
min / max .min() / .max()最小・最大。 範囲(max - min)と組み合わせて使うことが多い。
std / var .std() / .var()標準偏差・分散。 グループ内ばらつきを表現。 「平均」の付帯情報として必須。
quantile .quantile(q)任意の分位数(q=0.25 で 25%、 q=0.5 で中央値)。
nunique .nunique()ユニーク値の数。 「グループ内で何種類あるか」を見たいときに。
first / last .first() / .last()グループ内の最初・最後の値。 時系列で頻用。
📝 演習問題:集計の腕を磨く 10 問
基本集計 :SSDSE-B-2026 で「47 都道府県の総人口(A1101)」を地方ブロック別に sum、 mean、 median で集計せよ。 結果がどう違うか比較。
加重平均 :「都道府県別の高齢化率」を、 人口で加重した「地方ブロックの加重平均高齢化率」を計算せよ。 単純平均との差を 200 字で考察。
多重集計 :1 つの agg() で、 人口の sum + 出生数の mean + 大学数の max を同時に集計せよ。
2 軸集計 :地方ブロック × 高齢区分(若い/標準/高い)でクロス集計(人口の sum)。
transform 活用 :各県の人口を「自県が所属する地方ブロックの平均人口」で標準化せよ。
カスタム関数 :地方ブロックごとに「人口最大の県名」を返す集計関数を定義せよ。
欠損対処 :欠損のある列を集計する際の挙動を dropna=True/False で比較。
並び順制御 :地方ブロックの集計結果を「北海道→東北→…」の順で出力するコードを書け。
ピボット表 :地方ブロック × 年度の 2 軸で「平均人口」のクロス表を作成(pivot_table 使用)。
感度分析 :集計関数を sum/mean/median と変えると、 「日本一の地方ブロック」がどう変わるか調べよ。
💥 失敗例:集計で「やってはいけない」5 つのパターン
❌ 失敗 1:単純平均で報告
SSDSE-B-2026 で「地方ブロックの平均高齢化率」を県の単純平均で計算。 鳥取県(小県)と東京都(大県)を同じ重みで扱い、 実態と乖離した数値を報告。 対処 :人口で重み付けした加重平均を使う。
❌ 失敗 2:ばらつき情報を捨てる
「関東の平均人口」だけ報告。 関東内に東京都(突出)と栃木県(小)の大きなばらつきがあるが、 1 つの数字で全てを語ってしまう。 対処 :mean と一緒に std/min/max を必ず取得。
❌ 失敗 3:暗黙の欠損処理
SSDSE の欠損列を集計したとき、 pandas が暗黙に欠損を無視して計算。 観測数が実は少ないのに「47 県の平均」と報告。 対処 :必ず count と一緒に集計し、 観測数を併記。
❌ 失敗 4:シンプソンのパラドックス
地方ブロック単位で集計した結果と、 全国合計の傾向が逆になる現象。 「地方ごとには A が優勢、 全国では B が優勢 」のような事態。 対処 :集計レベルを変えた感度分析。
❌ 失敗 5:単位の取り違え
SSDSE の「千人」と「人」の単位を混ぜて集計し、 桁が違う数字を比較。 対処 :列名に単位を付ける、 派生列で正規化。
📔 集計 専用用語辞典(25 語)
集計(Aggregation) 個票を要約統計量に変換する操作。 SQL の GROUP BY と等価。
groupby pandas のグループ化メソッド。 集計の中核。
集約関数(Aggregation Function) グループ内の値を 1 つに圧縮する関数。 sum/mean/median 等。
キー(Key) グループ分けの基準列。 SSDSE では「Prefecture」「Block」等。
ピボットテーブル(Pivot Table) 2 軸(行×列)で集計したクロス表。 Excel と同じ概念。
transform 集計結果を元の行数のまま返すメソッド。 標準化や偏差計算に。
加重平均(Weighted Average) 重みを考慮した平均。 SSDSE で「人口加重高齢化率」など。
単純平均(Simple Average) 全ての値を等重みで平均。 加重平均との対比。
シンプソンのパラドックス 集計レベルで結論が逆転する現象。 統計入門の重要トピック。
Tidy Data 「1 行 = 1 観測、 1 列 = 1 変数」の整理形式。 集計しやすい構造。
ワイド形式 / ロング形式 横に広い vs 縦に長い形式。 SSDSE-B-2026 はワイド。
melt / pivot ワイド↔ロング変換。 集計前後の整形に頻用。
クロス集計(Cross Tabulation) 2 つ以上のカテゴリ変数のクロス表。 pandas の crosstab。
rolling 時系列の移動窓集計。 移動平均など。
expanding 累積集計(最初から現在まで)。 累積合計など。
resample 時系列の時間単位での集計(日次→月次など)。
window 関数 SQL の OVER 句。 ランキング・累積・差分に。
層化集計(Stratified Aggregation) 層を区別して集計し、 後で重み付け統合。
階層集計 複数階層(都道府県→地方→全国)で集計。
スパース集計 非ゼロ要素のみ集計する効率化技法。
近似集計 HyperLogLog などで巨大データを近似集計。
ストリーミング集計 データ到着順に逐次集計(Kafka, Flink)。
OLAP キューブ 多次元集計を高速化するデータ構造。
CUBE / ROLLUP SQL の高度な集計演算子。 全組合せ・階層集計。
DAX / Power Query Excel/Power BI の集計言語。 ビジネス現場で頻用。
🔬 発展トピック 8 つ
1. SQL の OVER 句と window 関数
「集計結果を元の各行に追加」を SQL で実現。 pandas の transform 相当。
2. CUBE / ROLLUP / GROUPING SETS
複数階層を一括集計する高度な SQL 演算子。 階層集計に必須。
3. HyperLogLog(近似集計)
数十億件のユニーク数を少メモリで近似計算。 ビッグデータ集計の主役。
4. ストリーミング集計(Flink / Kafka Streams)
無限ストリームをウィンドウ単位で集計。 リアルタイム分析。
5. プライバシー保護集計
差分プライバシーで集計結果にノイズを加算し、 個人を特定不可に。 SSDSE のような公開統計でも採用検討中。
6. 分散集計(MapReduce / Spark)
複数マシンで並列集計。 Spark の groupByKey や reduceByKey。
7. 階層的集計(OLAP)
「全国 → 地方 → 都道府県 → 市区町村」のような階層を効率的に集計。 BI ツールの定番機能。
8. シンプソンのパラドックスの対処
複数レベルで集計感度分析を実施。 因果推論の枠組み(Pearl の do 計算)で根本対応。
⚡ 集計を高速化する 10 のテクニック
1. カテゴリ型化
df['Block'] = df['Block'].astype('category')。 groupby の高速化と省メモリ。 SSDSE-B-2026 の都道府県名・地方ブロックは必須。
2. observed=True
groupby('Block', observed=True)。 存在しないカテゴリの出力を抑制。
3. 不要列を drop
集計前に集計対象外の列を drop。 メモリ使用量を削減。
4. インデックス活用
頻繁にグループ化するキーを set_index。 検索が高速化。
5. Polars への移行
巨大データ(GB クラス)なら Polars。 pandas より 5-10 倍高速。
6. DuckDB SQL
SQL を内蔵 DB で実行。 CSV を直接クエリ可能。 SSDSE 程度なら 1 秒未満。
7. Dask による並列化
マルチコア・分散環境で pandas 互換 API。 集計の並列化。
8. NumPy 直接利用
単純な sum/mean は NumPy の方が高速。 pandas オーバーヘッド回避。
9. Numba JIT コンパイル
カスタム集計関数を Numba で JIT。 ループ集計が C 並みの速度に。
10. キャッシュ活用
頻繁に使う集計結果を pickle・parquet で保存。 同じ計算を繰り返さない。
🚫 集計のアンチパターン 8 選
1. for ループ集計
「for pref in pref_list:」のような明示ループ。 groupby なら 100 倍高速。
2. 集計後の forループ
集計結果に対して再度 for ループでフィルタ。 ベクトル演算で十分。
3. 平均だけ報告
「ブロック平均は X です」だけ。 標準偏差・count を併記すべき。
4. 単位無視の比較
「千人」と「人」を混ぜて集計し、 桁違いの数字を並べる。
5. 順序の無視
地方ブロックを辞書順(北海道→九州沖縄)で並べる。 地理順を明示すべき。
6. NaN の無自覚処理
欠損値を 0 として集計し、 実態と乖離。 dropna=False で確認。
7. 元データ破壊
集計時に元データを上書き。 後で復元できず再読込が必要。 df.copy() 必須。
8. 単一集計関数依存
「とりあえず mean()」で全てを語る。 sum/median/std も併用。
🔄 集計ツール対応表(pandas / SQL / Excel / R)
操作 pandas SQL Excel R (dplyr)
グループ化 df.groupby('k')GROUP BY kピボットテーブル group_by(k)
合計 .sum()SUM(x)SUMIF summarise(sum(x))
平均 .mean()AVG(x)AVERAGEIF summarise(mean(x))
中央値 .median()PERCENTILE_CONT(0.5)MEDIAN summarise(median(x))
カウント .size()COUNT(*)COUNTIF summarise(n())
フィルタ df[cond]WHEREフィルタ機能 filter()
グループ後フィルタ .filter()HAVING手動 filter()
行に展開 .transform()OVER (PARTITION BY)VLOOKUP mutate(group_by())
🔗 集計と結合の合せ技
SSDSE-B-2026 と外部データを集計してから結合する典型ワークフロー。
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 import pandas as pd
# block_map はこのあとのブロックで作っているので、ここでも用意しておく
_pref = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' ,
skiprows = [ 1 ])[ 'Prefecture' ] . unique ()
def _blk ( code_i ):
if code_i == 1 : return '北海道'
if 2 <= code_i <= 7 : return '東北'
if 8 <= code_i <= 14 : return '関東'
if 15 <= code_i <= 23 : return '中部'
if 24 <= code_i <= 30 : return '近畿'
if 31 <= code_i <= 35 : return '中国'
if 36 <= code_i <= 39 : return '四国'
return '九州沖縄'
block_map = { p : _blk ( i + 1 ) for i , p in enumerate ( _pref )}
import pandas as pd
# SSDSE-B-2026 を地方ブロックで集計
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ], na_values = [ '-' ])
df [ 'Block' ] = df [ 'Prefecture' ] . map ( block_map )
block_summary = df [ df [ 'SSDSE-B-2026' ] == 2023 ] . groupby ( 'Block' ) . agg ({
'A1101' : 'sum' ,
'A1303' : 'sum' ,
'G7101' : 'sum' ,
}) . reset_index ()
block_summary [ 'aging_rate' ] = block_summary [ 'A1303' ] / block_summary [ 'A1101' ]
block_summary [ 'hotel_per_capita' ] = block_summary [ 'G7101' ] / block_summary [ 'A1101' ]
# 外部データ(例: 自分で取った地方ブロック別アンケート)
external = pd . read_csv ( 'data/raw/block_survey.csv' )
# 集計済み SSDSE と外部データを Block で結合
merged = block_summary . merge ( external , on = 'Block' , how = 'left' )
print ( merged )
💼 ビジネスでの集計シナリオ 5 種
シナリオ 1:月次経営レポート
売上を「店舗 × 商品カテゴリ × 月」で集計。 前月比・前年比を併記。 経営会議の根拠データ。
シナリオ 2:顧客セグメント分析
RFM 指標(Recency / Frequency / Monetary)を顧客別に集計。 セグメント分けでマーケティング最適化。
シナリオ 3:従業員エンゲージメント
満足度アンケートを部署別・職位別・勤続年数別に集計。 課題のある層を特定。
シナリオ 4:品質管理レポート
不良品データを工場別・製造ライン別・時間帯別に集計。 不良率の高い箇所を特定し原因分析。
シナリオ 5:自治体の住民サービス
SSDSE-B-2026 と自治体の窓口データを集計し、 「住民層別の利用パターン」を可視化。 サービス改善の根拠に。
💭 集計の哲学:「情報を捨てる勇気」
集計は情報を捨てる操作 です。 1000 の個票を 1 つの平均値に圧縮するとき、 999 個分の情報が失われます。 これを勇気を持って捨てる のが集計の本質です。
逆説的ですが、 情報を捨てるほど意思決定に有用 になります。 「47 都道府県の数値」を見せられても判断不能、 「8 地方ブロックの傾向」なら把握可能。 重要なのは「どの情報を残し、 どれを捨てるか 」の選択眼です。
SSDSE-B-2026 自体が、 個票(家計調査・労働力調査)を都道府県単位に集計したものです。 すでに膨大な情報を捨てた状態。 そこからさらに地方ブロックに集計するなら、 「失うものと得るもの 」を意識的に区別しましょう。 失うのはばらつき・例外、 得るのは概観・意思決定の速さ。
📈 SSDSE-B-2026 集計実例:地方ブロック比較表
SSDSE-B-2026 の 2023 年度データを地方ブロック別に集計した実例(実測値。 高齢化率は人口加重:A1303 合計 ÷ A1101 合計)。
地方 県数 総人口 平均人口 加重高齢化率 人口最大県
北海道 1 509 万 509 万 33.0% 北海道
東北 6 832 万 139 万 33.5% 宮城県
関東 7 4,353 万 622 万 26.2% 東京都
中部 9 2,075 万 231 万 29.7% 愛知県
近畿 7 2,199 万 314 万 29.2% 大阪府
中国 5 707 万 141 万 32.0% 広島県
四国 4 358 万 89 万 34.4% 愛媛県
九州沖縄 8 1,403 万 175 万 30.6% 福岡県
この表 1 枚で「日本の地域構造」が概観できます。 集計の威力です。
📝 集計結果の報告テンプレート
集計結果を読み手が誤解なく解釈できるよう、 報告には次の 7 要素を必ず含めます。
1. 出典・期間・対象
「SSDSE-B-2026(教育用標準データセット、 独立行政法人統計センター)、 2023 年度、 47 都道府県」を明記。
2. 集計キー
「地方ブロック(8 区分)」「年齢階級(5 区分)」など、 明示的に。
3. 集計関数
「sum / mean / median / 加重平均」のいずれを使ったか。 加重なら重み変数も明記。
4. サンプル数
各グループの n。 グループによって n が大きく異なる場合は要注意。
5. ばらつき情報
std、 min、 max、 IQR 等。 平均値だけでは不十分。
6. 単位
表のタイトル・列見出しに必ず単位を明記(人、 千人、 円、 %)。
7. 限界・注意
「単純平均のため小県も大県も等重みで計算」のような注意書き。
🧠 集計のドメイン知識:地方ブロックの選び方
SSDSE-B-2026 で「地方ブロックで集計」と言っても、 ブロックの定義は複数あります。
分類方式 区分数 用途
8 地方区分 8 最も一般的(北海道・東北・関東・中部・近畿・中国・四国・九州沖縄)
7 地方区分 7 沖縄を九州に含む(教科書的)
10 地方区分 10 気象庁が使用(北陸・東山・東海を別建て)
経済産業局 9 経済政策の単位
三大都市圏 3+1 東京圏・大阪圏・名古屋圏 vs 地方
東日本/西日本 2 スポーツ・電力会社境界(50/60Hz)
どれを使うかは分析目的次第。 必ず明示しましょう。
📊 集計後の統計検定 5 種
集計してグループ間に差があるか検定する典型手法。
1. χ² 検定(独立性)
クロス集計表の独立性検定。 「地方ブロックと高齢化区分は独立か」など。
2. ANOVA(一元配置分散分析)
3 群以上の平均差検定。 「地方ブロック別の人口に有意差はあるか」など。
3. Kruskal-Wallis 検定
ANOVA のノンパラ版。 正規分布を仮定しない。
4. 多重比較補正(Bonferroni / Tukey)
複数の組み合わせ検定を行う際の補正。 α=0.05 を比較数で割る等。
5. ブートストラップ信頼区間
集計値の不確実性を再標本化で推定。 SSDSE のような少サンプル時に有効。
🔬 数式を言葉で読み解く(補講: 集約操作 4 パターン)
集約 (aggregation) は「データを少数の代表値に縮約する」操作。 pandas の groupby + agg で実現する 4 つの典型パターンを SSDSE-B-2026 で順に試す。
▶ ブロック 1: 単純集約 (mean / sum / count)
このコードでやること : SSDSE-B-2026 を読み込み、 年度ごとの「総人口」の平均・合計・件数を一括で計算。 これが集約の最も基本形。
📥 入力データ (抜粋):
year, Code, Prefecture, A1101, ...
2023, R01000, 北海道, 5092000, ...
2023, R13000, 東京都, 14086000, ...
📋 コピー import pandas as pd
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ])
df = df . rename ( columns = { 'SSDSE-B-2026' : 'year' })
# 年ごとに「総人口 A1101」の平均・合計・件数を集約
res = df . groupby ( 'year' )[ 'A1101' ] . agg ([ 'mean' , 'sum' , 'count' ])
print ( res . tail ( 5 ))
📤 実行例:
mean sum count
year
2019 2.692660e+06 126555000 47
2020 2.683960e+06 126146099 47
2021 2.670213e+06 125500000 47
2022 2.658426e+06 124946000 47
2023 2.645809e+06 124353000 47
💬 年度ごとに平均・合計・カウントを 1 行で得られる。 mean は「県あたり平均人口」、 sum は「全国合計」、 count は「都道府県数=47」を確認。 日本の人口減少が定量的に読み取れる。
▶ ブロック 2: 複数列に別々の集約関数を適用
このコードでやること : 年ごとに「総人口 A1101 は平均」「延べ宿泊者数 G7101 は合計」を同時に集約。 列ごとに異なる関数を指定する dict 形式を使う。
📋 コピー res2 = df . groupby ( 'year' ) . agg ({
'A1101' : [ 'mean' , 'std' ],
'G7101' : [ 'sum' , 'mean' ],
})
print ( res2 . tail ( 3 ))
📤 実行例:
A1101 G7101
mean std sum mean
year
2021 2.670213e+06 2.791886e+06 258876760 5.508016e+06
2022 2.658426e+06 2.793536e+06 377170570 8.024906e+06
2023 2.645809e+06 2.797551e+06 499904350 1.063626e+07
💬 列ごとに違う関数を一括適用できるのが agg(dict) の利点。 結果は MultiIndex 列になるので、 後の処理は .droplevel() や .swaplevel() で整形する。
▶ ブロック 3: カスタム関数で「変動係数」を集約
このコードでやること : 標準ライブラリにない指標 (例: 変動係数 = std/mean) を lambda で定義し、 年度ごとに集約。 ばらつきの「相対的大きさ」を観察。
📋 コピー def cv ( x ):
return x . std () / x . mean ()
res3 = df . groupby ( 'year' ) . agg ({
'A1101' : cv ,
'G7101' : cv ,
})
res3 . columns = [ '人口の変動係数' , '延べ宿泊者数の変動係数' ]
print ( res3 . tail ( 3 ))
📤 実行例:
人口の変動係数 延べ宿泊者数の変動係数
year
2021 1.045567 0.971364
2022 1.050823 1.108046
2023 1.057352 1.285837
💬 2023 年は延べ宿泊者数の変動係数 1.29 > 人口の変動係数 1.06 → 宿泊需要の地域集中は人口分布より偏りが大きい。 なお 2021 年は 0.97 < 1.05 とコロナ禍で逆転しており、 年ごとの構造変化まで集約で追える。 平均で潰されがちな「ばらつき」を可視化できる実例。
▶ ブロック 4: 多階層 groupby + ピボット
このコードでやること : 「年度 × 地域」でクロス集約。 都道府県を「東日本/西日本」のグループにマップし、 年度別に総人口の合計を pivot 表示する。
📋 コピー east = { '北海道' , '青森県' , '岩手県' , '宮城県' , '秋田県' , '山形県' , '福島県' , '茨城県' , '栃木県' , '群馬県' ,
'埼玉県' , '千葉県' , '東京都' , '神奈川県' , '新潟県' , '富山県' , '石川県' , '福井県' , '山梨県' , '長野県' }
df [ 'region' ] = df [ 'Prefecture' ] . apply ( lambda x : '東日本' if x in east else '西日本' )
pv = df . groupby ([ 'year' , 'region' ])[ 'A1101' ] . sum () . unstack ()
print ( pv . tail ( 3 ))
📤 実行例:
region 東日本 西日本
year
2021 65188000 60312000
2022 64964000 59982000
2023 64723000 59630000
💬 東日本は西日本より約 1.09 倍人口が多い(2023 年)。 多階層 groupby + unstack で「クロス集計表」が即座に得られる。 BI ツールの pivot 機能に近い操作。 BI ツール や 可視化 の前処理として頻出。
🧮 実値で計算してみる(SSDSE-B-2026)
SSDSE-B-2026.csv の 47 都道府県を、 8 つの地方ブロック (北海道・東北・関東・中部・近畿・中国・四国・九州沖縄)にグループ化し、 総人口 A1101 を合計 する例を見てみる。 2023 年度の実測値(万人)で示す。
地方ブロック
含まれる都道府県(数)
総人口(万人)
平均人口(万人)
全国シェア(%)
北海道 1 509 509.2 4.1
東北 6 832 138.6 6.7
関東 7 4353 621.8 35.0
中部 9 2075 230.5 16.7
近畿 7 2199 314.1 17.7
中国 5 707 141.4 5.7
四国 4 358 89.4 2.9
九州沖縄 8 1403 175.4 11.3
全国合計 47 12435 264.6 100.0
表から:関東ブロック単独で全国人口の約 35% を占める (4353/12435)。 これは個別の 47 行を眺めるだけでは見えにくい構造。 集計が「視点を変える」ことが分かる典型例。
同様に 出生数 A4101 を集計すれば「東日本 vs 西日本での子ども数の偏り」、 大学数 E6102 を集計すれば「高等教育インフラの地域偏在」が浮かび上がる。
補助計算:65 歳以上人口比(高齢化率)の地方ブロック平均
SSDSE-B-2026 の列 A1303(65 歳以上人口)/A1101(総人口)から県別高齢化率を計算し、 地方ブロックごとに単純平均をとると下表のようになる(2023 年度・実測値)。
地方ブロック
高齢化率の平均 (%)
最小県 (%)
最大県 (%)
北海道 33.0 33.0 33.0
東北 34.5 29.2 39.1
関東 28.0 22.8 31.0
中部 31.3 25.7 33.9
近畿 30.3 27.0 34.2
中国 33.0 30.1 35.4
四国 34.6 32.5 36.3
九州沖縄 31.5 23.8 34.3
同じ集計でも 「合計」 なら関東が日本一だが、 「平均高齢化率」 なら四国(34.6%)・東北(34.5%)が上位に来る。 集計関数を変えると見える社会構造が反転する のがよく分かる。
🧮 数式に値を入れて手で計算する
少数の代表的サンプル $x = [3, 5, 8, 2, 7]$ に対し、 代表的な集計関数 (合計・平均・最小・最大・分散・標準偏差) の数式を逐次代入する。 同じ計算を Python (numpy) で再現し、 結果が完全一致することを確認する。 SSDSE-B-2026 (47 都道府県の A1101 人口など) でのスケールアップは、 本セクション冒頭の地方ブロック集計表と「🐍 Python 実装」セクションを参照。
📐 集計関数の数式 (再掲)
$$ \text{sum} = \sum_{i=1}^{n} x_i, \quad \bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_i, \quad s^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2, \quad s = \sqrt{s^2} $$
Step 1: データ準備 (合成、 多様な整数)
Step 2: 基本集計 (合計・平均・最小・最大)
項目 計算 結果
$n$ 要素数 5
合計 $\sum x_i$ $3 + 5 + 8 + 2 + 7$ 25
平均 $\bar{x}$ $25 / 5$ 5.0
最小 $\min(3,5,8,2,7)$ 2
最大 $\max(3,5,8,2,7)$ 8
Step 3: 偏差と偏差平方 ($\bar{x} = 5$)
$x_i$ $x_i - \bar{x}$ $(x_i - \bar{x})^2$
3 $-2$ 4
5 $0$ 0
8 $+3$ 9
2 $-3$ 9
7 $+2$ 4
合計 0 26
Step 4: 分散と標準偏差 (不偏、 $n-1$ で割る)
項目 計算 結果
分散 $s^2$ $26 / (5-1) = 26/4$ 6.5
標準偏差 $s$ $\sqrt{6.5}$ 2.549510
🐍 同じ計算を Python で再現
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 import numpy as np
# Step 1: 代表サンプル
x = np . array ([ 3 , 5 , 8 , 2 , 7 ])
# Step 2: 基本集計
print ( f "n = { len ( x ) } " )
print ( f "sum = { x . sum () } " )
print ( f "mean = { x . mean () } " )
print ( f "min = { x . min () } " )
print ( f "max = { x . max () } " )
# Step 3-4: 分散・標準偏差 (不偏: ddof=1)
print ( f "var = { x . var ( ddof = 1 ) } " )
print ( f "std = { x . std ( ddof = 1 ) : .6f } " )
📤 実行結果
n = 5
sum = 25
mean = 5.0
min = 2
max = 8
var = 6.5
std = 2.549510
💬 手計算 (Step 2〜4) と Python 出力が完全一致 (sum=25, mean=5.0, var=6.5, std=2.549510)。 同じ 5 個の数でも 6 種類の集計値を取り出せることが「集約」の本質である。
🎮 触って理解する
左側の 個票(1 点 = 1 観測) を上下にドラッグ、 または下のスライダーで値を変えると、 右側の グループ別「集約値」の棒グラフ がリアルタイムで更新されます。 上のボタンで 集約関数(合計 / 平均 / 中央値 / 最大 / 最小 / 件数) を切り替え、 「同じデータでも関数を変えると見える景色が反転する」ことを体感してください。 データは説明用の 架空のサンプル値 です(SSDSE の実測値ではありません)。
🧠 この操作から掴んでほしいこと
直感:集約とは「粒度を粗くして要約する」こと。 個票(左の点)が何個あっても、 集約関数を通すとグループごとに たった 1 つの数 に潰れます。 行数が必ず減り、 情報が圧縮される――これが GROUP BY 的な集計の核心です。 「合計」ボタンでは点が多い/値が大きいグループの棒が高くなり、 「件数」ボタンでは値の大小と無関係に 点の個数だけ が棒の高さになります。 同じ配置でも、 関数を変えるだけで棒の順位が入れ替わることを確認してください。
⚠️ よくある落とし穴(このウィジェットで再現できる)
情報損失: 集約すると 元の個票には戻れません 。 「平均 50」という 1 つの数からは、 中身が [50,50,50] なのか [10,50,90] なのか区別できません。 平均だけを報告するとばらつき(分散)が消えます。 だから実務では mean と一緒に std / min / max / count を必ず併記します。
平均の誤解(外れ値に引っ張られる): どれか 1 点を上端までドラッグして「平均」と「中央値」を見比べてください。 平均は外れ値に大きく動くのに、 中央値はほとんど動きません。 外れ値 の多いデータでは、 平均より中央値 のほうが「代表値」として頑健です(ロバスト統計 )。
Simpson のパラドックス: 集約の粒度を変えると結論が逆転することがあります。 グループ別に集約した傾向と、 全部を 1 つにまとめて集約した傾向が食い違う現象です。 「どのキーで束ねたか」を変えるだけで物語が反転しうるため、 集約レベルを変えた感度分析が欠かせません。
🚀 発展
実データでは、 このトグルが pandas の df.groupby(key).agg(func) の func 差し替えに対応します。 さらに一歩進むと、 グループのサイズ(件数)で重みづけした 加重平均 、 2 つのキーで束ねる 多段集約 (→ ピボットテーブル )、 集約結果を元の行数に戻す transform などがあります。 「どのキー(groupby )で・どの関数(平均 /中央値 ほか)で束ねたか」を必ず明記することが、 再現可能な集約の第一歩です。 中心傾向の指標選びは 代表値 のページも参照してください。
🐍 Python 実装
SSDSE-B-2026 を読み込んで、 47 都道府県を地方ブロックで集計する完全コード。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口) A4101(出生数) E6102(大学数)
北海道 5,092,000 24,430 37
東京都 14,086,000 86,348 144
沖縄県 1,468,000 12,549 8
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 import pandas as pd
# 1) SSDSE-B-2026 読み込み (1行目が英語コード、2行目が日本語ラベル、3行目以降データ)
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ])
# 2) 都道府県を地方ブロックにマッピング
block_map = {
'北海道' : '北海道' ,
'青森県' : '東北' , '岩手県' : '東北' , '宮城県' : '東北' , '秋田県' : '東北' , '山形県' : '東北' , '福島県' : '東北' ,
'茨城県' : '関東' , '栃木県' : '関東' , '群馬県' : '関東' , '埼玉県' : '関東' , '千葉県' : '関東' , '東京都' : '関東' , '神奈川県' : '関東' ,
'新潟県' : '中部' , '富山県' : '中部' , '石川県' : '中部' , '福井県' : '中部' , '山梨県' : '中部' ,
'長野県' : '中部' , '岐阜県' : '中部' , '静岡県' : '中部' , '愛知県' : '中部' ,
'三重県' : '近畿' , '滋賀県' : '近畿' , '京都府' : '近畿' , '大阪府' : '近畿' , '兵庫県' : '近畿' , '奈良県' : '近畿' , '和歌山県' : '近畿' ,
'鳥取県' : '中国' , '島根県' : '中国' , '岡山県' : '中国' , '広島県' : '中国' , '山口県' : '中国' ,
'徳島県' : '四国' , '香川県' : '四国' , '愛媛県' : '四国' , '高知県' : '四国' ,
'福岡県' : '九州沖縄' , '佐賀県' : '九州沖縄' , '長崎県' : '九州沖縄' , '熊本県' : '九州沖縄' ,
'大分県' : '九州沖縄' , '宮崎県' : '九州沖縄' , '鹿児島県' : '九州沖縄' , '沖縄県' : '九州沖縄' ,
}
df [ 'Block' ] = df [ 'Prefecture' ] . map ( block_map )
# 3) 2023 年度の 47 都道府県に絞ってから groupby で集計(複数の集計関数を同時適用)
# ※ SSDSE-B-2026 は 2012-2023 年度のパネル。絞らないと 12 年分が混ざる
df = df [ df [ 'SSDSE-B-2026' ] == 2023 ]
agg = df . groupby ( 'Block' ) . agg (
都道府県数 = ( 'Prefecture' , 'count' ),
総人口 = ( 'A1101' , 'sum' ),
平均人口 = ( 'A1101' , 'mean' ),
出生数合計 = ( 'A4101' , 'sum' ),
大学数合計 = ( 'E6102' , 'sum' ),
)
print ( agg . sort_values ( '総人口' , ascending = False ))
# 4) 全国シェアを追加
agg [ '人口シェア(%)' ] = agg [ '総人口' ] / agg [ '総人口' ] . sum () * 100
print ( agg )
📤 実行例(実測)
都道府県数 総人口 平均人口 出生数合計 大学数合計
Block
関東 7 43527000 6.218143e+06 252911 267
近畿 7 21990000 3.141429e+06 132406 158
中部 9 20749000 2.305444e+06 121110 144
九州沖縄 8 14029000 1.753625e+06 93109 80
東北 6 8318000 1.386333e+06 41237 52
中国 5 7070000 1.414000e+06 42468 54
北海道 1 5092000 5.092000e+06 24430 37
四国 4 3578000 8.945000e+05 19598 18
都道府県数 総人口 平均人口 出生数合計 大学数合計 人口シェア(%)
Block
中国 5 7070000 1.414000e+06 42468 54
…(以下略)
2 軸集計とピボットテーブル
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import os
os . makedirs ( 'outputs' , exist_ok = True ) # 書き出し先を先に作る
# 仮の年齢区分列を追加(65歳以上人口 A1303 / 総人口 A1101 で高齢化率)
df [ '高齢化率' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ '高齢区分' ] = pd . cut ( df [ '高齢化率' ], bins = [ 0 , 0.25 , 0.30 , 1.0 ], labels = [ '若い' , '標準' , '高い' ])
# 2軸の集計
two_way = df . groupby ([ 'Block' , '高齢区分' ], observed = True ) . size () . unstack ( fill_value = 0 )
print ( two_way )
# ピボットテーブル形式
pv = df . pivot_table (
index = 'Block' ,
values = [ 'A1101' , 'A4101' , 'E6102' ],
aggfunc = [ 'sum' , 'mean' ],
)
print ( pv )
# Excel/CSV に書き出し
pv . to_csv ( 'outputs/region_pivot.csv' , encoding = 'utf-8-sig' )
📤 実行例(実測)
高齢区分 若い 標準 高い
Block
中国 0 0 5
中部 0 1 8
九州沖縄 1 1 6
北海道 0 0 1
四国 0 0 4
東北 0 1 5
近畿 0 4 3
関東 1 3 3
sum mean
A1101 A4101 E6102 A1101 A4101 E6102
Block
中国 7070000 42468 54 1.414000e+06 8493.600000 10.800000
中部 20749000 121110 144 2.305444e+06 13456.666667 16.000000
九州沖縄 14029000 93109 80 1.753625e+06 11638.625000 10.000000
北海道 5092000 24430 37 5.092000e+06 24430.000000 37.000000
四国 3578000 19598 18 8.9450
…(以下略)
カスタム集計関数(lambda・apply)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 # 各地方ブロックで「人口最大の県」を取り出す
def top_pref ( group ):
idx = group [ 'A1101' ] . idxmax ()
return group . loc [ idx , 'Prefecture' ]
top_by_block = df . groupby ( 'Block' ) . apply ( top_pref )
print ( top_by_block )
# 北海道 -> 北海道、関東 -> 東京都、近畿 -> 大阪府、九州沖縄 -> 福岡県 …
# 加重平均:人口で重み付けした高齢化率(県を単純平均しない)
def weighted_aging ( group ):
return ( group [ 'A1303' ] . sum () / group [ 'A1101' ] . sum ()) * 100
w_aging = df . groupby ( 'Block' ) . apply ( weighted_aging )
print ( w_aging . round ( 2 ))
📤 実行例(実測)
Block
中国 広島県
中部 愛知県
九州沖縄 福岡県
北海道 北海道
四国 愛媛県
東北 宮城県
近畿 大阪府
関東 東京都
dtype: object
Block
中国 32.01
中部 29.69
九州沖縄 30.59
北海道 33.01
四国 34.38
東北 33.54
近畿 29.21
関東 26.17
dtype: float64
transform:集計結果を元の行に戻す
📋 コピー # 各県の人口を「自県が所属する地方ブロック総人口」で割って、 ブロック内シェアを計算
df [ 'ブロック内人口シェア(%)' ] = df . groupby ( 'Block' )[ 'A1101' ] . transform ( lambda x : x / x . sum () * 100 )
print ( df [[ 'Prefecture' , 'Block' , 'A1101' , 'ブロック内人口シェア(%)' ]] . head ( 10 ))
# 関東ブロックでは東京都が約 32%、 神奈川県が約 21% を占めることがわかる
📤 実行例(実測)
Prefecture Block A1101 ブロック内人口シェア(%)
0 北海道 北海道 5092000 100.000000
12 青森県 東北 1184000 14.234191
24 岩手県 東北 1163000 13.981726
36 宮城県 東北 2264000 27.218081
48 秋田県 東北 914000 10.988218
60 山形県 東北 1026000 12.334696
72 福島県 東北 1767000 21.243087
84 茨城県 関東 2825000 6.490224
96 栃木県 関東 1897000 4.358214
108 群馬県 関東 1902000 4.369702
補足:df.groupby(...).transform(...) は集計結果を 元の行数のまま 返すので、 「県の値をブロック平均と比較したい」「ブロック内偏差を計算したい」ようなケースに最適。
🐍 集計の発展実装例
SSDSE-B-2026 で全 110 列を一括集計
📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年)
年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) …
2023 R01000 北海道 5,092,000 1,681,000 24,430 …
2023 R13000 東京都 14,086,000 3,205,000 86,348 …
2023 R47000 沖縄県 1,468,000 350,000 12,549 …
…(残り 112 列は住宅・家計・教育・医療など)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import os
os . makedirs ( 'outputs' , exist_ok = True ) # 書き出し先を先に作る
import pandas as pd
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ], na_values = [ '-' ])
df [ 'Block' ] = df [ 'Prefecture' ] . map ( block_map )
df = df [ df [ 'SSDSE-B-2026' ] == 2023 ] # 2023 年度の 47 都道府県に絞る
# 数値列を全て地方ブロック平均で集計
num_cols = df . select_dtypes ( include = 'number' ) . columns . tolist ()
block_means = df . groupby ( 'Block' )[ num_cols ] . mean ()
block_means . to_csv ( 'outputs/block_all_means.csv' , encoding = 'utf-8-sig' )
# 数値列を全て地方ブロック標準偏差で集計
block_stds = df . groupby ( 'Block' )[ num_cols ] . std ()
block_stds . to_csv ( 'outputs/block_all_stds.csv' , encoding = 'utf-8-sig' )
DuckDB で SQL 集計
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import duckdb
# 生 CSV には Block 列がないので、pandas で Block 列を付与した
# DataFrame(df)をそのまま SQL でクエリする(DuckDB の replacement scan)
result = duckdb . query ( '''
SELECT
Block,
SUM(A1101) AS total_pop,
AVG(A1101) AS avg_pop,
STDDEV(A1101) AS std_pop,
COUNT(*) AS n_prefs
FROM df
WHERE "SSDSE-B-2026" = 2023
GROUP BY Block
ORDER BY total_pop DESC
''' ) . to_df ()
print ( result )
Polars で高速集計
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口)
北海道 5,092,000
東京都 14,086,000
沖縄県 1,468,000
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import pandas as pd
import polars as pl
# polars は cp932 を直接読めないため、pandas で読み込んで変換する
pdf = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ], na_values = [ '-' ])
pdf [ 'Block' ] = pdf [ 'Prefecture' ] . map ( block_map )
df = pl . from_pandas ( pdf )
result = (
df . lazy ()
. filter ( pl . col ( 'SSDSE-B-2026' ) == 2023 )
. group_by ( 'Block' )
. agg ([
pl . col ( 'A1101' ) . sum () . alias ( 'total_pop' ),
pl . col ( 'A1101' ) . mean () . alias ( 'avg_pop' ),
pl . col ( 'A1101' ) . std () . alias ( 'std_pop' ),
pl . len () . alias ( 'n_prefs' ),
])
. sort ( 'total_pop' , descending = True )
. collect ()
)
print ( result )
Polars は遅延評価(lazy)で複雑なパイプラインも最適化。 pandas より 5-10 倍高速。 巨大データの集計で重宝します。 SSDSE 程度なら pandas で十分ですが、 文法を覚えておくと業務で役立ちます。
⚠️ 落とし穴
❌ 集計後は元データに戻れない
都道府県別の値を地方ブロックに合計してしまうと、 ブロック内の県間ばらつき(分散)は失われる。 必要なら std/var/min/max も同時に取って 付帯情報 として残しておくこと。 集計の前に df.copy() でバックアップを取る癖もつけたい。
❌ 合計と平均で見える物語が逆転する
関東は 総人口 では圧倒的トップだが、 平均人口 でも他ブロックより大きい一方、 1 県あたりの面積・密度では別の順序になる。 「合計」「平均」「中央値」を取り違えないこと。 報告書では必ず 使用した集計関数の種類 を明記。
❌ 欠損値の暗黙の扱い
pandas の sum() はデフォルトで NaN を 0 として無視する。 SSDSE で欠損のある列を集計すると 暗黙のうちに観測数が変わる 。 df.groupby(...).agg('count') で件数も同時に確認するのが鉄則。
❌ groupby のキー型
カテゴリ列は astype('category') にしておかないと 順序が辞書順 になり、 地方ブロックを北海道→東北→…で並べたいのに北海道→九州→…になることがある。 表示順を明示する pd.Categorical([...], categories=[...], ordered=True) が便利。
❌ 単純平均と加重平均の混同(「平均の平均」の罠)
各県の「高齢化率」をブロック内で単純平均すると、 鳥取(小県)も東京(大県)も同じ重みになる。 県別の
平均 (率)をさらに平均する「
平均の平均 」は、 グループごとの件数(人口)が異なる限り全体の真の平均と一致しない。 人口比に応じた
加重平均 をしたい場合は
(group['A1303'].sum() / group['A1101'].sum()) のように分子分母を別々に sum する。 これは
シンプソンのパラドックス (集計レベルで結論が逆転する現象)と並ぶ、 集約の二大落とし穴。
⚠️ 集計のアンチパターン徹底解説
「集計で炎上した」事例は、 ほぼ全てここで挙げる 7 つのアンチパターンに収まる。 SSDSE-B-2026 のような公的データを扱うとき、 自分の集計が以下のどれかに該当していないか必ずチェックしよう。
アンチパターン 1:「全国平均」だけで地方差を語る
SSDSE で「日本の高齢化率は約 29%(2023 年度・人口加重で 29.1%)」と発表することは可能だが、 これは 四国の 34.4% と関東の 26.2% を丸ごと均した結果 であり、 どの地方の実態とも一致しない。 「平均的な日本人」は統計上の幻想で、 実在しない。 地方差を語るなら必ず 地方ブロック別の集計 を併記すること。
アンチパターン 2:単位を統一せずに合計
SSDSE-B-2026 の各列は「人」「円」「件」「‰」と単位がバラバラ。 集計時に df[['A1101','L3221']].sum() のように「人」の列と「円」の列を混ぜて合計しても意味のない値が出る。 必ず 列ごとの単位を辞書で管理 し、 単位が揃った列だけ集計するのが安全。
アンチパターン 3:欠損を無視して mean
特殊指標列(沖縄のみ計測、 都市部のみ計測など)を集計すると、 NaN が多いブロックほど「実は少数県の平均」になり、 全国比較で誤解を生む。 集計時に count を併記すれば、 「どの程度の県を見た値か」が明示される。
アンチパターン 4:median を取らず外れ値を放置
日本の都道府県人口の分布は東京(1,409 万)など少数の大県に大きく歪んでいる。 47 都道府県の人口を mean で取ると約 265 万人だが、 median は約 155 万人(2023 年度・実測)と 100 万人以上も小さい。 外れ値・歪みの影響を抑えたいなら median を併記。 一般的に「分布が歪んでいるなら median を主、 mean を副 」が安全。
アンチパターン 5:時系列差を考えず最新年だけ集計
最新の 2023 年度だけ集計して「東北は人口 832 万」と書いても、 2012 年度は 916 万 (11 年で約 84 万人減)だった事実は見えない。 「水準」と「変化」を 必ずセットで提示 すること。 政策論議では変化のほうが重要なことが多い。
アンチパターン 6:集計値を四捨五入しすぎる
「関東の人口は約 4 千万人」とザックリ言うのは便利だが、 43,527 千人(2023 年度・実測) ↔ 44,000 千人 の差は約 47 万人(数十万人レベル)。 政策議論ではこの差が大きい。 集計値の精度はデータの精度に合わせ、 不必要な丸めをしない 。
アンチパターン 7:因果と集計を取り違える
「四国は高齢化率が高い → だから経済が停滞」のような 集計値からの因果推論 は危険。 集計はあくまで 記述統計 であり、 因果関係を示すには別の枠組み(回帰分析・自然実験)が必要。 「集計したら相関があった」を「因果がある」と読み替えないこと。
📊 集計を「図」で確かめる(SSDSE-B-2026)
集計は数値だけでは「本当にそうなっているのか 」が分かりにくい。 必ず 図 で確認するのが鉄則。 ここでは SSDSE-B-2026 の都道府県データを地方ブロックで集計した結果を、 3 種類の標準的な図で示す。 それぞれ 異なる側面 を映し出すことに注目してほしい。
① 散布図:集計前の個票(47 県)と集計後の代表値の関係
下図は SSDSE-B-2026 の総人口 A1101 と一般診療所数 I5102 の 都道府県別散布図 (2023 年度・r = 0.97)。 集計せず 47 点をそのまま打つことで、 「個票レベルでどれだけのばらつきがあるか」が一目で分かる。 集計(地方ブロック単位の sum や mean)はこの散布図を 8 点に圧縮 する操作であり、 当然ながら個別の県名・各点の散らばりは失われる。 集計値だけを見ていると、 「東京単独で外れ値的に大きい」といった構造を見落としかねない。 集計を行う 前後 を必ず可視化で対比するのが、 データ分析の基本作法。
図1: 集計前の個票(47 都道府県)。 集計するとこの散らばりは 8 点に圧縮される。
散布図のメッセージ:「集計後の 8 点だけを見せる」のは情報損失のリスクがある。 レポートでは 集計値と個票散布図を併記 することで、 「平均だけ見て判断する」誤りを避けられる。
② ヒストグラム:集計対象列の分布形
集計関数 sum / mean / median のどれを選ぶかは、 元データの分布形 で決まる。 下のヒストグラムは SSDSE-B-2026 の 47 都道府県の総人口分布(2023 年度)で、 「強い右に長い裾を持つ分布 」(東京・神奈川・大阪・愛知が大きく外れる)であることを示している。 こうした分布で mean(平均)を取ると、 一部の大きな値に強く引きずられる。 中央付近の代表値を取りたいなら median を、 全体規模を表したいなら sum を使う。 「分布を見ずに集計関数を選んではいけない 」というのが鉄則。
図2: 集計対象列の分布形。 右に長い裾がある分布では平均と中央値で大きく結論が変わる。
ヒストグラムのメッセージ:分布形が対称なら mean、 歪んでいるなら median を採用するのがセオリー。 集計の冒頭で必ずヒストグラムを描く 1 行(df['A1101'].hist())を加えるだけで、 「平均を取ったら中央値とまったく違った」事故を防げる。
③ 箱ひげ図:複数グループの代表値とばらつきを同時に見る
集計の結果を「8 地方ブロック × 1 つの集計値」として見せるのが棒グラフだが、 これでは ブロック内のばらつき (東北の最高齢化県と最若年化県の差など)が消える。 そこで箱ひげ図を使う。 下図は SSDSE-B-2026 の一般診療所数を KMeans クラスタ別に描いたもので、 各グループの中央値・第 1〜第 3 四分位・外れ値を一目で示す典型例。 SSDSE-B-2026 でいえば、 「地方ブロック × 高齢化率」「地方ブロック × 1 県あたり人口」を箱ひげ図で描けば、 集計値(平均)と 同時にばらつき を確認できる。
図3: 複数グループの代表値とばらつきを同時に表示する箱ひげ図。 集計の「平均だけ」では見えない情報。
箱ひげ図のメッセージ:集計後の 1 数値(平均など)だけでなく、 第 1〜第 3 四分位 と外れ値を併記することで、 「同じ平均でもばらつきが違うグループ」を見落とさずに済む。 SSDSE-B-2026 でいえば、 関東は平均人口が大きいだけでなく、 ブロック内のばらつき(東京 1,409 万 vs 栃木 190 万)が東北(最大宮城 226 万 vs 最小秋田 91 万)よりはるかに大きい、 という事実が箱ひげで初めて見える。
図と表を組み合わせるベストプラクティス
図の種類
何を見せるか
SSDSE-B-2026 での活用
表との役割分担
散布図 個票(集計前)の関係 総人口 vs 一般診療所数(47 県) 表は集計後、 図は集計前
ヒストグラム 集計対象列の分布形 A1101 の右に長い裾 関数選択の根拠を示す
箱ひげ図 グループ間の代表値とばらつき 地方ブロック × 高齢化率 集計値の妥当性を裏付ける
棒グラフ 集計後の代表値そのもの 地方ブロック別の人口合計 表の数値を視覚化
ヒートマップ 2 軸集計の濃淡 地方 × 高齢区分のクロス表 pivot_table を一目で確認
レポートの構成順は 「ヒストグラム → 集計表 → 棒グラフ or 箱ひげ図」 が王道。 まず分布形を確認し、 集計関数を選ぶ根拠を読者に示し、 集計結果を表で示し、 視覚的に強調する図を最後に添える。 この順序を守ると、 読者は「なぜこの集計関数を選んだのか」「集計値はどの程度信頼できるか」を自然に理解できる。
🧪 SSDSE-B-2026 の集計を 4 つの観点で深掘り
SSDSE-B-2026(47 都道府県 × 約 110 列)の集計を、 4 つの分析軸 で具体的に練習する。 単なる sum / mean を超えて、 「集計の設計が分析の質を決める 」ことを実感できる構成にした。 公的統計ならではの注意点も併記する。
観点 1:人口関連列(A1xxx 系)の地方ブロック集計
SSDSE-B-2026 で最も基本的な集計対象は人口関連列(A1101 総人口、 A1301 年少人口、 A1302 生産年齢人口、 A1303 老年人口)。 これらを地方ブロックで sum すれば「ブロック合計人口」、 mean すれば「1 県あたり平均人口」、 さらに比率を計算すれば「ブロック別の高齢化率」が出る。 重要なのは、 3 種類の年齢区分の合計が総人口とほぼ一致する こと(丸めの影響で全国計は千人単位のずれが出る)。 集計後にこの恒等式が成り立つか必ず検算しよう。
地方ブロック
A1101 合計 (千人)
A1301 年少 (千人)
A1302 生産年齢 (千人)
A1303 老年 (千人)
高齢化率 (%)
北海道 5,092 514 2,897 1,681 33.0
東北 8,318 870 4,657 2,790 33.5
関東 43,527 4,810 27,327 11,390 26.2
中部 20,749 2,423 12,166 6,161 29.7
近畿 21,990 2,512 13,053 6,423 29.2
中国 7,070 836 3,972 2,263 32.0
四国 3,578 394 1,955 1,230 34.4
九州沖縄 14,029 1,812 7,927 4,291 30.6
全国 124,353 14,171 73,954 36,229 29.1
読み方:人口の 絶対量 では関東が圧倒的(全国の 35.0%)。 高齢化率(人口加重)では 四国(34.4%) が最も高く、 関東は逆に最低(26.2%)。 集計関数を sum から比率に変えるだけで、 同じデータから正反対の地域構造 が見えるのが分かる(2023 年度・実測値)。
観点 2:教育・労働列の集計と「正規化」の重要性
SSDSE-B-2026 の E 列(教育)や F 列(労働)を地方ブロックで集計すると、 絶対量 はほぼ人口に比例してしまう。 そこで「人口で割る」「シェアで表す」といった 正規化 が必須になる。 たとえば大学数 E6102 を集計するだけでなく、 「人口千人あたりの大学数」 を計算することで、 「地方別の高等教育インフラ密度」が見える(下表は 2023 年度・実測値)。
地方ブロック
大学数 (校)
人口 (千人)
千人あたり大学数
大学シェア (%)
北海道 37 5,092 0.0073 4.6
東北 52 8,318 0.0063 6.4
関東 267 43,527 0.0061 33.0
中部 144 20,749 0.0069 17.8
近畿 158 21,990 0.0072 19.5
中国 54 7,070 0.0076 6.7
四国 18 3,578 0.0050 2.2
九州沖縄 80 14,029 0.0057 9.9
読み方:絶対数(大学シェア %)では関東 33.0% で圧倒的(全国 810 校中 267 校)。 だが 千人あたり大学数 で見ると中国(0.0076)・北海道(0.0073)・近畿(0.0072)が関東(0.0061)を 上回り 、 最低は四国(0.0050)。 集計結果は必ず「絶対量」「正規化値」の 2 つの軸 で読むこと。
観点 3:複数集計関数を一括適用(agg(['sum','mean','std']))
pandas の agg は複数の集計関数を同時に適用できる。 これにより「1 回の groupby で sum / mean / std / min / max を全部出す 」ことが可能。 結果は MultiIndex の列(地方ブロック × {sum, mean, std, min, max})になる。 ばらつき(std)も同時に取れるのが利点で、 「平均は同じでも分散が違うグループ」を即座に見抜ける。
地方ブロック
sum (人口)
mean
std
min
max
CV=std/mean
東北 8,318 1,386 521 914 2,264 0.38
関東 43,527 6,218 4,491 1,897 14,086 0.72
中部 20,749 2,305 2,133 744 7,477 0.93
近畿 21,990 3,141 2,899 892 8,763 0.92
九州沖縄 14,029 1,754 1,386 795 5,103 0.79
読み方:CV(変動係数)= std/mean はばらつきを mean で正規化した指標。 中部 0.93・近畿 0.92 → 1 都府県の規模差が大きい(愛知・大阪が突出)。 東北は 0.38 と最も均質。 集計時に std を併記するだけで、 「同じ平均でも構造が違う」が一目で分かる(2023 年度・実測値、 単位:千人)。
観点 4:時系列集計(resample, rolling)の応用
SSDSE-B-2026 はそれ自体が 2012〜2023 年度の 12 年 × 47 都道府県のパネルデータ 。 そのまま「年×地方ブロック」の 2 軸集計や、 「3 年移動平均」(rolling)を取れば、 短期変動を均した長期トレンドが見える。 時系列集計は resample('Y')(年次)、 rolling(window=3).mean()(移動平均)が代表的。 SSDSE のような中規模公的データでは、 これらが組み合わさることで初めて「地方別の人口減少ペース 」「東京一極集中の進行速度 」が定量化できる。
年
関東人口 (千人)
東北人口 (千人)
関東/全国 (%)
3 年移動平均 (関東)
2015 42,995 8,983 33.8 42,856
2017 43,333 8,850 34.1 43,168
2019 43,627 8,695 34.5 43,481
2021 43,561 8,519 34.7 43,614
2023 43,527 8,318 35.0 43,541
読み方(2012〜2023 年度・実測値、 単位:千人。 移動平均は年次系列から計算):関東は 2012→2023 で +874 千人 (ただし 2020 年度の 43,653 千人をピークに微減に転じている)、 東北は −840 千人 (明確な減)。 関東/全国シェアは 33.4% → 35.0% と着実に上昇 = 一極集中の進行が定量化できる。 単年集計(観点 1〜3)では見えない「変化のスピード」は、 時系列集計でのみ捉えられる。
🛠 集計設計の意思決定フレーム
「どの列をどう集計するか」は、 機械的に決まらない設計判断。 ここでは 5 ステップ の意思決定フレームを示す。 SSDSE-B-2026 を集計する前に、 必ずこの順序でレビューすると、 「集計したけど分析が刺さらない」事故を回避できる。
ステップ 1:分析の問い(research question)を 1 文で書く 。 例:「東日本と西日本で、 高等教育インフラの密度に差があるか?」「地方別の人口減少ペースを比較する」。 問いがないと「キー」「集計関数」「正規化」がすべて恣意的になる。
ステップ 2:集計キーを 1 つに絞る(あるいは 2 軸交差にする) 。 SSDSE では「都道府県(47)」「地方ブロック(8)」「年(時系列)」「年齢区分(3)」が代表的キー。 粒度が細かすぎる(47 県)と集計の効果が薄く、 粗すぎる(東西 2 分)と情報損失が大きい。 8 地方ブロック が「意思決定の粒度」と「統計的安定性」のバランス点。
ステップ 3:集計関数を選ぶ(sum / mean / median / std) 。 絶対量を見たいなら sum、 県あたり水準なら mean、 外れ値の影響を抑えたいなら median、 ばらつきを併記したいなら std。 ヒストグラムで分布形を確認してから決める。
ステップ 4:正規化が必要か判断 。 「人口当たり」「面積当たり」「世帯当たり」など、 分母を決めて比率に変えると、 大きさの効果を取り除いた純粋な構造が見える。 SSDSE の E 列・F 列・H 列はほぼ常に正規化が必要。
ステップ 5:図と表で検算 。 集計結果を表で示すだけでなく、 必ず棒グラフ・箱ひげ図・ヒートマップなどで視覚化。 「数値の合計が全国合計と一致するか」も検算(恒等式チェック)。
このフレームを SSDSE-B-2026 の集計に適用すると、 たとえば「東日本 vs 西日本で大学数密度を比較したい」という問いに対し、 キー=東西 2 ブロック / 集計関数=sum + 人口で正規化 / 図=棒グラフ、 という設計が機械的に導ける。 集計の「思いつき」を「設計」に変えるのが、 このフレームの目的。
よくある集計設計の失敗パターン
失敗パターン
何が問題か
修正方針
問いを決めずに groupby 何を主張したいかが不明で、 集計値を眺めるだけになる ステップ 1 で問いを 1 文化
sum を取って規模差を比較 人口が大きいブロックが必ず勝つ。 構造が見えない 人口・面積で正規化(ステップ 4)
外れ値を含めたまま mean 東京 1 県で関東 mean が引っ張られる median を併記、 ヒストグラムで分布確認
集計後にばらつきを忘れる 平均だけでは「均質か散らばっているか」が分からない std や CV を併記、 箱ひげ図
恒等式チェックをしない A1301+A1302+A1303 ≠ A1101 のミスを見落とす 合計列の和が全国合計と一致するか検算
単一の集計関数だけで結論 sum vs mean vs median で結論が反転することを見落とす agg(['sum','mean','median']) を癖にする
🌐 関連手法・派生
集計は単独で完結する操作ではなく、 前後の操作と組み合わさって威力を発揮する。
🌐 追加リソース
日本語
pandas 公式ドキュメント(日本語訳あり):groupby の章
『Pythonによるデータ分析入門』第 9 章「データ集約とグループ演算」
e-Stat:政府統計の総合窓口(SSDSE 元データ)
独立行政法人統計センター SSDSE ページ:教育用標準データセット
英語
pandas Cookbook (Wes McKinney)
『SQL for Data Analysis』O'Reilly
『Practical SQL』No Starch Press
『Statistics in a Nutshell』O'Reilly
🏁 集計の最終メッセージ
集計はデータ分析の入口でありながら、 もっとも誤解されやすい操作 です。 単純平均と加重平均、 sum と mean、 dropna の有無で、 結果は大きく変わります。 「とりあえず集計 」ではなく、 何を残し何を捨てるか を意識した集計を心がけてください。
SSDSE-B-2026 を題材に df.groupby('Block').agg(...) を 100 回唱えれば、 体に染み込みます。 集計が体に染み込んだとき、 あなたはデータ分析の「最初の壁」を超えています。
❓ 集計 Q&A(拡張版)
Q. SSDSE-B-2026 で「最も人口の多い地方ブロック」はどこ?
A. 圧倒的に関東。 約 4,350 万人(2023 年度)で全国の 35%。 集計関数を sum で取れば一目瞭然。 ただし、 mean を取ると北海道が「1 県 = 1 ブロック」なので別の話。
Q. ピボットテーブルと groupby、 どちらを使うべき?
A. 2 軸でクロス集計したいなら pivot_table、 縦持ちで後続処理(merge / plot)に流したいなら groupby。 SSDSE-B-2026 の「地方 × 年」のクロス表は pivot_table が読みやすい。
Q. 集計後に元データに戻りたい
A. 戻れません。 集計は不可逆操作 。 集計前に df.copy() でバックアップ必須。 もしくは集計しながら元情報を保持したいなら、 transform を使う。
Q. 巨大データで groupby が遅い
A. ①列を category 化、 ②不要列を drop、 ③observed=True で省メモリ、 ④Polars / DuckDB に移行。 SSDSE-B-2026 程度(数千行)なら pandas で十分。
Q. シンプソンのパラドックスとは?
A. 「地方ごとには A が優勢、 全国では B が優勢 」のような集計レベルで結論が逆転する現象。 SSDSE-B-2026 でも起きうるので、 必ず複数レベルで集計確認。
💀 拡張失敗例:実務で見かける 8 つの罠
罠 1:「平均より上」の罠
「全国平均より高齢化率が高い都道府県は…」と語るとき、 「全国平均」は単純平均か加重平均か。 SSDSE で単純平均を使うと、 県ごとに人口が違うので、 真の意味の「平均的高齢化率」とは別物になる。
罠 2:「全国合計=47県合計」と思い込む
SSDSE-B-2026 には「全国」行はないが、 公表統計側で示される「全国値」は 47 県の合計と必ず一致するわけではない(推計方法・丸めの違い)。 実際、 2023 年度の年齢 3 区分の合計と総人口の全国計にも千人単位のずれがある。
罠 3:年次データを月次と混同
SSDSE-B-2026 は年次データ。 月次の e-Stat データと結合するときに集計レベルの揃え方を間違える。
罠 4:率と数値の混同
「高齢化率」(%)を sum で集計してしまう。 率は加重平均か、 分子と分母を別々に sum して比を計算する。
罠 5:カテゴリ列の暗黙ソート
「地方ブロック」を文字列のまま groupby すると、 辞書順「中国→中部→九州沖縄→北海道→…」と並ぶ。 意味的順序に直す。
罠 6:欠損を 0 とした集計
「データなし」と「0」は別概念。 sum でも mean でも結果が変わる。 欠損は dropna で明示。
罠 7:時系列の累積を取り違える
「2012-2023 の人口合計」と語るとき、 12 年分の人口を sum すると意味のない数字(延べ人口×12)。 SSDSE-B-2026 はパネルデータなので、 年度で絞らずに sum するとまさにこの事故が起きる。
罠 8:単一集計関数で全てを語る
mean だけで結論。 sum / median / std を併用するだけで、 解釈の幅が広がる。
🔮 集計の未来:2026 年以降のトレンド
1. Polars の普及
pandas 互換 API + Rust 実装 + 並列処理で 5-10 倍高速。 巨大データ集計の主役に。
2. DuckDB の主流化
SQL で CSV/Parquet を直接クエリ。 「集計 = SQL」回帰。 学習コストが下がる。
3. ストリーミング集計の一般化
バッチ集計と並んで、 リアルタイム集計(Kafka / Flink)が標準スキルに。
4. プライバシー保護集計
差分プライバシーで集計結果にノイズを加算し、 個人を特定不可に。 公的統計でも段階的に採用。
5. LLM を使った集計の自然言語化
「SSDSE で関東の人口を集計して 」と自然言語で指示し、 LLM が SQL/pandas コードを生成する時代に。 ただし結果の妥当性は人間が確認すべき。
📖 集計の哲学的考察:「個と全体」の往復運動
集計は単なる数値計算ではなく、 「個別の現実 」と「全体の傾向 」を行き来する知の運動 です。 SSDSE-B-2026 の 47 都道府県の個別値を 8 地方ブロックに圧縮するとき、 私たちは「個」を捨てて「全体」を得ています。 この選択は政治的・哲学的に深い意味を持ちます。
「個別性の擁護」と「総括の必要性」のジレンマ
「沖縄は本州と気候も歴史も違うのに、 同じブロックに入れていいのか 」「東京の特殊性は関東に埋もれてしまわないか 」というジレンマは常につきまといます。 完璧な答えはなく、 分析目的に応じて使い分ける のが現実解。 ただし、 集計の境界線を引く瞬間に「誰かの個別性を切り捨てている 」自覚は持つべきです。
集計の倫理:誰に説明責任があるか
SSDSE-B-2026 を集計して「関東は高齢化率が低い 」と報告するとき、 その数値の背後にいる関東 4,300 万人 1 人 1 人に対して、 集計者は説明責任を持ちます。 集計は「顔の見える人々を見えなくする操作 」だからこそ、 慎重さが求められます。
集計と意思決定の関係
経営判断・政策判断は集計された情報 に基づいて行われます。 集計が偏れば判断も偏ります。 「集計関数の選択」というテクニカルな問題が、 数百万人の生活に影響する判断につながるのです。 だからこそ、 集計には誠実さ が必要です。
📋 集計の本質を 5 行で
集計は情報を意図的に捨てる 操作。 残すものと捨てるものを意識せよ。
集約関数(sum/mean/median)の選び方で結論が変わる 。 必ず併記。
SSDSE-B-2026 のような実データで、 欠損・単位・順序 を必ず確認。
加重平均が必要なケースを見抜け。 SSDSE では「率の平均」で頻出。
集計結果を報告するとき、 サンプル数・ばらつき・限界 を必ず併記。
🎓 集計はデータ分析の入口にして奥義 。 SSDSE-B-2026 で 100 回唱えて、 体に染み込ませてください。 関連用語ページ(groupby 、 ピボット 、 相関 、 線形回帰 )を併読すると、 知識のネットワークが完成します。
📚 集計を学んだ後に進むべき道
集計を体得した後、 次に進むべき技法・領域を整理する。 SSDSE-B-2026 を出発点として、 どの方向に学習を広げると効果的かを示す。 集計はゴールではなく、 データ分析の旅路の最初の一歩 。
結合(join / merge) :集計した結果と別データを結合することで、 「地方ブロック別の人口集計 × 経済指標」「県別の医療指標 × 公衆衛生統計」といったクロスドメイン分析 が可能になる。 集計の双対概念として必修。
可視化の高度化 :matplotlib / seaborn の基本を超え、 plotly / altair で インタラクティブダッシュボード を作る。 集計結果を「読み手が探索できる形」で提示することで、 政策議論の質が変わる。
統計的検定 :「東日本と西日本で高齢化率に有意差はあるか?」のような問いには、 集計値だけでなく t 検定・カイ二乗検定 などの検定が必要。 集計の延長として学ぶと自然に身につく。
回帰分析 :集計値を説明変数・被説明変数として扱う回帰モデル(OLS、 ロジスティック回帰)。 集計の「水準」と「変化」を統計的に説明する次のステップ。
因果推論 :集計値だけでは「相関」しか見えない。 自然実験・操作変数法・差の差分析(DiD)など、 因果関係を厳密に議論するフレームへ。 SSDSE のような観察データでは特に重要。
機械学習 :集計結果を特徴量として扱い、 クラスタリング・分類・予測モデルを構築。 集計の出力が ML パイプラインの入力になる典型例。
時系列分析 :SSDSE の年次パネル(2012〜2023)を活用し、 集計値の時間的変化を ARIMA や状態空間モデルでモデル化。
地理空間分析 :47 都道府県・8 地方ブロックを地図上にプロット。 集計値をコロプレス(色塗り地図)で可視化することで、 「東京一極集中」「西高東低の高齢化」といった構造が空間的に把握できる。
集計を 「データ分析の OS のような基盤技術」 として位置づけ、 その上に上記の高度な技法を積み上げていく。 SSDSE-B-2026 を扱う本コンペは、 まさにその学習の起点として最適。 集計の習得は単なる pandas のテクニックではなく、 データから社会を読み解き、 政策に貢献する 力を育てる第一歩である。
最後に強調したいのは、 集計は 「単純な操作だからこそ奥が深い」 ということ。 pandas の groupby を 1 行書くだけで実行できるが、 その 1 行に込められた 「キー選択」「関数選択」「正規化」「検算」「可視化」「ストーリーテリング」 のすべてが、 アナリストの実力を映す。 SSDSE-B-2026 の集計を通じて、 その奥行きを体感し、 自分なりの集計哲学を持てるようになれば、 本コンペでの学習目的は十分達成されたといえる。 集計は道具であり、 哲学であり、 そして社会との対話手段である。
本ページで学んだ集計の流儀をもとに、 ぜひ自分の関心領域(地方創生・公衆衛生・教育格差・経済政策など)に SSDSE-B-2026 の集計を当てはめ、 自らの仮説をデータで検証する経験を積んでほしい。 集計は誰でも始められる第一歩であり、 同時に 生涯学習可能な深い領域 でもある。 47 都道府県のデータを 8 ブロックに圧縮する作業ひとつにも、 統計学・社会学・政策論・データエンジニアリングのすべてが交わる豊かな世界が広がっている。 そしてその世界の入口に立つには、 たった 1 行の df.groupby('Block').agg(...) から始めればよい。 SSDSE-B-2026 を題材にした集計の旅が、 読者にとって有意義な学習体験になり、 そして将来の社会的意思決定に貢献する確かな礎となり、 多くの方の学びへとつながることを心から願っている。
✅ SSDSE-B-2026 集計のセルフチェックリスト
SSDSE-B-2026 を集計するとき、 提出前に必ず通すチェックリスト。 30 項目を順番に確認することで、 集計起因のミスを最小限にできる。 コンペ提出・レポート公開の直前に必ず実施しよう。
フェーズ 1:データ読み込み(5 項目)
□ 文字コード(cp932 / utf-8)を明示したか
□ skiprows で日本語ラベル行を除外したか
□ 県コードを文字列型として読み込んだか
□ df.shape で 564 行(12 年 × 47 県)× 112 列を確認したか(2023 年度に絞ると 47 行)
□ df.head() / df.tail() で先頭・末尾の県を確認したか
フェーズ 2:前処理(5 項目)
□ 都道府県名 → 地方ブロックのマッピング辞書を作ったか
□ map 後の NaN(マッピング漏れ)がないか確認したか
□ 数値列を pd.to_numeric で適切な型に変換したか
□ 欠損値の分布(df.isna().sum())を確認したか
□ 単位が揃った列のみ集計対象にしたか
フェーズ 3:集計実行(10 項目)
□ 集計キーを明示的に決定したか
□ 集計関数を sum / mean / median / std で並列適用したか
□ count 列を併記して「何県の平均か」を示したか
□ 加重平均が必要な指標で誤って単純平均していないか
□ 正規化(シェア・千人あたり)を計算したか
□ 集計結果の合計と元データ合計が一致するか検算したか
□ NaN の扱い(dropna)を意識的に選択したか
□ 集計結果に MultiIndex があるか確認し、 reset_index したか
□ 集計結果のサイズ(行数 = ブロック数)が想定通りか
□ 集計結果を CSV / Parquet で保存したか
フェーズ 4:可視化・レポート(10 項目)
□ 集計対象列のヒストグラムを先に描いたか(分布形の確認)
□ 集計結果を棒グラフで可視化したか
□ ばらつきを箱ひげ図で示したか
□ 時系列があれば折れ線で変化を示したか
□ 単位を図のラベルに明記したか
□ 「だから何?」の解釈文を 1-2 文で添えたか
□ 集計手続き(キー・関数)を本文で明記したか
□ 限界事項(外れ値の影響、 因果ではない)を注釈したか
□ レポートに更新日とデータ出典を明記したか
□ 第三者が再現できるコード一式を添付したか
30 項目を全部通過すれば、 SSDSE-B-2026 を使った集計レポートとして プロ水準 と言える。 学習段階では 1 つずつ意識的にやることでチェックリストを身体化し、 やがて反射的にすべてを満たせるようになるのが目標。
💎 集計を 1 段引き上げる 12 のティップス
実務で集計を扱う中で「これは知っておきたかった」というティップスを 12 個まとめた。 SSDSE-B-2026 のような公的統計の集計で、 すぐに効果が出る具体策。
カラム名は英数字のみにする :「総人口」のような日本語列名は集計コードでミスを生む。 SSDSE のように A1101 のコードを使ったほうが安全。 表示時だけ日本語に変換。
集計関数の組み合わせを定型化 :agg(['sum','mean','median','std','count']) をデフォルトに。 ばらつき情報を毎回取る習慣で「分散が大きいが平均が同じ」という構造を見落とさない。
集計の前に必ず df.info() :型・欠損数・サイズを把握してから集計。 これだけで「文字列を sum しようとして失敗」「欠損だらけの列で mean が無意味」を防げる。
集計キーは事前に check :df['Block'].value_counts() でキーの分布を確認。 「沖縄が単独カテゴリになっていた」「東京が NaN になっていた」を集計前に発見できる。
正規化列を自動追加 :集計結果に 'シェア(%)' = col/col.sum()*100 を必ず添える関数を作る。 絶対量と正規化値を両方見せるのが正義。
集計結果に「単位」を列名に書く :'人口_千人' のように、 列名から単位が分かるようにする。 SSDSE のような複数単位混在データで威力を発揮。
集計後の検算を自動化 :assert agg['人口'].sum() == df['A1101'].sum() のようにテストを入れる。 集計バグを CI で検知できる。
plotly / altair のインタラクティブグラフを使う :集計結果を matplotlib だけで見せず、 ホバーで詳細が出るインタラクティブグラフにすると、 読み手が自分で深掘りできる。
集計の「サンプル数」を必ず表示 :mean だけ見せても「3 県の平均か 30 県の平均か」で信頼性が違う。 count 列を併記するだけで信頼性の議論ができる。
集計結果は WideFormat より LongFormat で保存 :縦持ち(long)のほうが後続の merge・plot で扱いやすい。 表示時だけ pivot で横持ちに。
集計のクエリログを残す :「いつ、 どの集計を、 何のために行ったか」を Markdown で記録。 後日「あの集計どうやったっけ」を防げる。
集計の出力に必ず「最終更新日」を入れる :データが更新されたら集計値も変わる。 SSDSE のように年次更新されるデータでは特に重要。 集計結果ファイル名に _20260530.csv のような日付サフィックスを。
この 12 項目はすべて 「集計を 1 回で終わらせず、 後から再利用・再現できる形にする」 ことを目的としている。 集計は「使い捨て」のように扱いやすいが、 1 回の集計が組織の意思決定 → 政策 → 数年後の影響 にまで波及することを意識すると、 ティップスの重みが分かる。 SSDSE-B-2026 を扱うコンペでも、 単に集計値を出すだけでなく、 上記の習慣を身につけながら作業を進めると、 後で見返したときに「自分の成長」が形として残る。
🧩 集計を「使いこなす」ための実践ガイド
最後に、 集計の学習者がよくぶつかる壁とその乗り越え方を 5 つの場面別に整理する。 SSDSE-B-2026 を扱う本コンペで 初学者からプロ並みの集計力 に至る道筋を示す。
場面 1:「どの列を集計すべきか分からない」
SSDSE-B-2026 には約 110 列あり、 初学者は「どこから手をつければいいか分からない」状態になりがち。 対処法:「自分が答えたい問い」を 1 文で書く → その問いに必要な列だけ抽出 → 集計、 という順序を守る。 例:「東京一極集中を確認したい」→ A1101(総人口)、 G7101(延べ宿泊者数)、 L3221(消費支出)、 これらを地方ブロック集計。 列の網羅性ではなく、 問いとの整合性 を重視。
場面 2:「集計結果が想定と合わない」
「関東の人口が 5000 万人を超えている!」のような 明らかにおかしい結果 が出たら、 必ず以下をチェック:① 単位(千人 vs 人)、 ② NaN の有無、 ③ 集計関数(sum vs mean を取り違えていないか)、 ④ 二重集計(既に集計済みデータをさらに集計していないか)、 ⑤ 結合の重複(merge 後に行が増えていないか)。 SSDSE 集計でよくある事故の 90% はこの 5 項目のどれか。 「想定と違う」と気づくこと自体が一番難しい ので、 集計前に「だいたいこのくらいになるはず」と紙に書く習慣をつけよう。
場面 3:「集計結果をどう見せるか迷う」
集計結果は表 + 図のセットで提示するのが基本だが、 「どの図か」で悩むことが多い。 ルール:① 量の大小を見せたい → 棒グラフ、 ② ばらつきを見せたい → 箱ひげ図、 ③ 変化を見せたい → 折れ線、 ④ 2 軸の関係を見せたい → ヒートマップ、 ⑤ 全体に占める割合 → 円グラフ(ただし円は読みにくいので棒グラフのほうが推奨)。 SSDSE-B-2026 の地方ブロック集計なら、 「棒 + 箱ひげ + 折れ線」の 3 枚セットがスタンダード。
場面 4:「集計コードが冗長になる」
同じような集計を何度も書いていると、 コードが長くなり保守が大変。 対処法:① よく使う集計を関数化(def agg_by_block(df, col):)、 ② パイプライン化(df.pipe(add_block).pipe(agg_by_block))、 ③ Jupyter のマジックコマンド(%store)で中間結果を保存。 SSDSE-B-2026 のような少数固定スキーマでは、 ライブラリ化までは不要だが、 関数化は積極的に 。 集計のコードは 「ノートブックの粗描き」から「再利用可能な関数」へ 育てていくのが王道。
場面 5:「集計結果を共有しても伝わらない」
「集計したのに上司や同僚に響かない」のは、 ほぼ 「集計の意義の説明不足」 が原因。 対処法:① 集計の前提(どんな問いに答えるか)を冒頭に書く、 ② 集計の手続き(キーと関数)を明示、 ③ 結果に「だから何?」を必ず添える、 ④ 数字だけでなく「物語」として提示する。 SSDSE で「四国の高齢化率 34.4%(2023 年度・人口加重)」と数字だけ示すより、 「四国は日本で最も高齢化が進む地域。 すでに人口の 3 人に 1 人以上が高齢者。 全国に先駆けて医療・介護の最適配分が必要」と物語化すれば、 行動に結びつく。
レベル
できること
SSDSE での到達目安
L1 初学者 groupby + sum / mean が書ける ブロック別人口合計を出せる
L2 中級 複数集計関数、 ピボット、 加重平均 複数指標を並列集計し、 ピボット表化
L3 上級 transform、 ランク、 移動平均、 仮説検証 時系列パネルでトレンド分析
L4 プロ 集計設計を意思決定文脈で語れる 政策提言につながるレポート作成
SSDSE-B-2026 を題材に L1 → L4 へ段階的に進むことが、 本コンペでの最重要学習目標の 1 つ。 集計は「データから社会を読み解く 」最も基本的かつ最も奥深い技法。 単なる pandas の操作にとどまらず、 分析の哲学とコミュニケーションの技術 として身につけたい。
🧭 集計を「正しく」設計するメンタルモデル
集計の設計力は経験で磨かれる部分が大きいが、 「こう考えるとブレない 」というメンタルモデルがある。 ここではプロのデータアナリストが暗黙的に持っている思考の枠組みを言語化する。
モデル 1:「集計はズームアウト操作」
Google Maps を縮尺 1/10,000 から 1/1,000,000 にズームアウトすると、 個別の建物は消え、 街区・都市・地域の構造が見える。 集計もまったく同じ操作で、 47 都道府県(縮尺 1)→ 8 地方ブロック(縮尺 6)→ 東西 2 地域(縮尺 24)→ 全国 1(縮尺 47) と段階的にズームアウトできる。 「どの縮尺で世界を見せたいか」を決めるのが集計設計の本質。 縮尺が違えば見えるもの・見落とすものが変わる。 必ず複数の縮尺で見比べる のがプロの作法。
モデル 2:「集計はレンズ選び」
同じ被写体(SSDSE-B-2026 のデータ)でも、 sum レンズで撮れば「絶対量」、 mean レンズで撮れば「水準」、 median レンズで撮れば「中央」、 std レンズで撮れば「ばらつき」が写る。 1 枚の写真だけで被写体を判断するのが危険なように、 1 つの集計値だけで結論を出すのも危険 。 必ず複数のレンズで撮り、 写真を並べて比較する。 これは pandas でいうと agg(['sum','mean','median','std']) を必ず併用する習慣。
モデル 3:「集計は仮説のテスト」
優れたアナリストは集計を 「仮説の検証」 として行う。 「東京一極集中が進んでいるはず」という仮説を持って、 「関東/全国シェアの時系列」を集計し、 仮説と一致するか確認する。 仮説なしの集計は探索的だが、 仮説ありの集計はストーリーが組み立てやすい 。 SSDSE を扱うときも「この集計で何が見えたら自分の仮説が正しい/間違いと言えるか」を先に書き出すと、 集計が単なる作業から知的探求に変わる。
モデル 4:「集計はストーリーテリングの素材」
最終的に集計値は 「読み手の意思決定を変える物語」 として提示される。 単なる数字の羅列ではなく、 「だから何?」「次に何をすべき?」と読み手に行動を促す形に整理する。 SSDSE-B-2026 の地方ブロック集計を例にすれば、 「四国は最も高齢化が進む → 医療・介護の重点配分が必要 → 具体的予算配分のシミュレーションへ」とつなげる。 集計はデータ分析の 終わりではなく始まり 。
メンタルモデル
対応する pandas 操作
SSDSE での具体応用
ズームアウト groupby のキー粒度を変える 県 → ブロック → 全国
レンズ選び agg(['sum','mean','median','std']) 複数集計関数を並列適用
仮説テスト 集計後に条件チェック 関東シェアが上昇しているか
ストーリーテリング 集計値 + 可視化 + 結論文 レポート最終章
「悪い集計」「良い集計」の対比表
観点
悪い集計
良い集計
問い 「とりあえず集計してみた」 「〇〇を明らかにしたい → だからこの集計」
キー 使えるキーを全部試す 意思決定の粒度に合わせて選ぶ
関数 mean だけ sum / mean / median / std を並列
正規化 絶対量のまま 人口・面積で正規化
可視化 表だけ 表 + ヒストグラム + 箱ひげ + 棒
解釈 「関東が大きい」で終わる 「だから〇〇を提案」まで踏み込む
再現性 手動の Excel 操作 pandas スクリプトを git 管理
検算 なし 全国合計との一致を確認
「良い集計」の各項目はそれぞれ独立した習慣だが、 全部を意識すると 1 集計あたり 5 倍くらい時間がかかる。 だからこそ テンプレート化 するのが重要。 自分なりの「集計テンプレート Notebook」を作り、 SSDSE のような新しいデータに対しても同じ構造で進められるようにしておくと、 圧倒的に効率が上がる。
📜 pandas 集計レシピ集 — SSDSE-B-2026 で即使える 20 パターン
SSDSE-B-2026 の集計でよく書く 20 パターンを 1 か所にまとめた。 「今度こういう集計したい」と思ったときにここを参照すれば、 ほぼコピー&ペーストで動かせる構成。 すべて pandas 2.x を前提とする。
No.
やりたいこと
レシピ(pandas コード)
1 ブロック別人口合計 df.groupby('Block')['A1101'].sum()
2 ブロック別人口平均 df.groupby('Block')['A1101'].mean()
3 ブロック別人口中央値 df.groupby('Block')['A1101'].median()
4 複数集計関数同時適用 df.groupby('Block')['A1101'].agg(['sum','mean','median','std'])
5 列ごとに異なる集計関数 df.groupby('Block').agg({'A1101':'sum','A4101':'mean'})
6 名前付き集計 df.groupby('Block').agg(総人口=('A1101','sum'), 平均人口=('A1101','mean'))
7 人口加重平均(高齢化率) df.groupby('Block').apply(lambda g: g['A1303'].sum() / g['A1101'].sum())
8 グループ内最大値の県名 df.loc[df.groupby('Block')['A1101'].idxmax(), ['Block','Prefecture']]
9 グループ内ランク df['rank_in_block'] = df.groupby('Block')['A1101'].rank(ascending=False)
10 グループ平均を各行に展開 df['block_mean'] = df.groupby('Block')['A1101'].transform('mean')
11 ピボットテーブル(地方 × 高齢区分) df.pivot_table(index='Block', columns='AgeBin', values='A1101', aggfunc='sum')
12 クロス集計(カウント) pd.crosstab(df['Block'], df['AgeBin'])
13 小計付きピボット df.pivot_table(index='Block', values='A1101', aggfunc='sum', margins=True)
14 全国シェア計算 (df.groupby('Block')['A1101'].sum() / df['A1101'].sum() * 100)
15 グループ内偏差(標準化前) df['z'] = df.groupby('Block')['A1101'].transform(lambda x: (x - x.mean()) / x.std())
16 条件付き集計(人口 200 万超のみ) df.query('A1101 > 2000').groupby('Block')['A1101'].sum()
17 グループ件数(unique count) df.groupby('Block')['Prefecture'].nunique()
18 分位点(25/50/75) df.groupby('Block')['A1101'].quantile([0.25,0.5,0.75])
19 NaN もキー扱い df.groupby('Block', dropna=False)['A1101'].sum()
20 複数キー集計(地方 × 年) df.groupby(['SSDSE-B-2026','Block'])['A1101'].sum().unstack()
これら 20 パターンを 「自分の手で 1 回ずつ実行」 すれば、 SSDSE-B-2026 の集計でつまずくことはほぼなくなる。 学習の順序としては、 1〜10(基本)→ 11〜15(ピボット・transform)→ 16〜20(応用)が推奨。 ノートブックの 1 セルずつに分けて、 出力を読みながら進めるのが効果的。
集計結果の保存と再利用
集計結果は 1 回の分析で使い切るものではなく、 後続の分析・可視化・モデリングで 何度も参照される中間成果物 。 そのため、 集計結果を CSV / Parquet で保存し、 ファイル名にキーと集計関数を明示する習慣をつけよう(例:aggregated_by_block_sum_2026.csv)。 git で版管理することで、 集計手続きが変わったときに過去結果との比較も容易になる。
保存形式
適性
SSDSE 集計での使い分け
CSV (utf-8-sig) Excel で開く前提、 共有しやすい レポート添付用
Parquet 列指向で高速、 型保存 パイプライン中段
JSON Web 連携、 構造化 ダッシュボード入力用
Pickle pandas DataFrame そのまま保存 短期的なキャッシュ
🌏 集計が支える社会的意思決定 — 公的統計・経済・科学
集計は単なるテクニカルな操作ではなく、 社会の動きを把握し、 政策を決めるための核心的なツール である。 SSDSE-B-2026 のような公的統計が、 集計を通じてどのように社会を動かしているかを 4 つの観点から整理する。
観点 A:人口政策と集計
国勢調査・住民基本台帳から得られる SSDSE-B-2026 の人口データは、 集計によって 「地方創生」「少子化対策」「医療資源配分」 の根拠となる。 たとえば「合計特殊出生率 A4103」を都道府県で比較すれば、 沖縄が突出して高く(2023 年度実測 1.60)、 東京が最低(同 0.99)、 という構造が見える。 これに基づき、 出生率の高い地域の生活習慣・支援制度を全国に展開する政策議論が生まれる。 集計値が 地域比較の共通言語 として機能する。
観点 B:経済指標と集計
GDP(国内総生産)は典型的な集計の結果。 企業の売上を業種別・地域別・年次で sum したものが、 国の経済規模を表す。 SSDSE-B-2026 で同じ「集計 → 正規化」の発想を試すなら、 たとえば延べ宿泊者数 G7101 を地方ブロックで sum すると「関東 1 ブロックで全国の宿泊需要の約 3 割(30.8%)」「四国は約 2%」という規模が見える。 さらに 1 人あたり(G7101 / 人口)に正規化すると、 北海道・九州沖縄など観光地の相対的な高さが浮かび、 規模の効果を取り除いた構造が見える。 集計と正規化のセットが経済・政策の議論を支える。
観点 C:科学研究と集計
医療研究では、 臨床試験の参加者を「処置群」「対照群」で集計し、 治療効果を比較する。 SSDSE のような社会統計でも、 同じ枠組みが使える。 たとえば「がん検診受診率」を都道府県別に集計し、 受診率の高い県と低い県で「がん死亡率」を比較すると、 検診の効果を間接的に推定できる。 集計は 疫学・公衆衛生研究の出発点 として機能する。 ただし因果推論には、 集計だけでなく交絡因子の調整(回帰分析・傾向スコア)が必須。
観点 D:報道・市民参加と集計
新聞・テレビが「東京一極集中」「地方の高齢化」と報道するときの根拠は、 ほぼすべて集計値。 集計表を見やすく可視化することで、 一般市民もデータに基づく議論に参加できる。 SSDSE-B-2026 のような公的統計がオープンデータとして公開されているのは、 まさに 市民が自ら集計し、 自分の住む地域を理解できる ようにするため。 集計のスキルは シビックテック (市民による技術参加)の基礎技能。
分野
集計の対象
集計キー
社会的アウトカム
人口政策 出生数、 死亡数、 転入転出 都道府県、 年齢階級 地方創生戦略、 子育て支援
経済政策 延べ宿泊者数、 消費支出 都道府県、 地方ブロック 観光振興策、 需要喚起策
医療・公衆衛生 受診者数、 死亡数、 入院日数 都道府県、 年齢、 疾病分類 医療資源配分、 検診促進
教育 大学数、 大学学生数、 高校卒業者数 都道府県、 設置者(国公私) 高等教育インフラ整備
環境 CO2 排出量、 廃棄物量 都道府県、 セクター(運輸、 産業) 脱炭素政策、 環境規制
災害対策 被害件数、 復旧支出 市町村、 災害種別 防災投資、 復興予算
上の表は公的統計全般での集計の使われ方であり、 SSDSE-B-2026 が直接カバーするのは人口・経済(宿泊・消費)・医療・教育などの一部(CO2 排出量・災害統計などは e-Stat 等の別統計)。 それでも SSDSE-B-2026 で扱う変数は、 こうした社会的意思決定の 基盤 になりうる。 集計のスキルを身につけるということは、 単に pandas を操作することではなく、 「社会のどの問題に答えるための集計か 」を考えながらデータを扱う訓練。 学習コンペにおいても、 集計値を「誰がどう使うか 」を意識して提示することで、 分析の説得力が劇的に上がる。
集計が「正しく機能する」ための社会的前提
集計値が政策議論で信頼されるためには、 以下の社会的前提が必要:
元データの精度 :国勢調査・住民基本台帳のような 悉皆的な公的データ があってこそ、 集計値が代表性を持つ。
集計手続きの透明性 :「どの列を、 どのキーで、 どの関数で集計したか」が公開され、 第三者が再現できる必要がある。 SSDSE はこの面で優秀。
集計値の解釈の共通言語 :「平均」「中央値」「シェア」の意味を、 行政・研究者・市民が共有していること。 統計教育の重要性。
集計の限界の明示 :「これは記述統計であり、 因果ではない」「外れ値の影響を受けている」と 注釈をつける文化 。
これらの前提が揃って初めて、 集計値が「社会的に意味のある数字」として機能する。 技術的に集計を行うことと、 社会的に集計値を使うことの間には、 大きなギャップがある。 そのギャップを埋めるのが データリテラシー教育 であり、 SSDSE のような教材を活用する意義である。
📖 集計に関する用語 25 件の徹底解説
集計の現場で混乱しやすい用語を 25 件、 SSDSE-B-2026 を例に解説する。 「言葉の意味を曖昧にしたまま集計すると、 必ず議論が空回りする」のが現実。 ここで用語を整理しておく。
用語
意味
SSDSE での具体例
aggregation 複数行を 1 行に要約する操作の総称 47 県 → 8 ブロック
grouping key 集計の単位を決める列 Block 列
aggregate function 複数値から 1 値を作る関数 sum, mean, median, std
pivot 縦持ちを横持ちに変換しつつ集計 行=Block、 列=高齢区分
crosstab 2 軸でカウントするピボットの特殊版 地方 × 高齢区分の度数表
resample 時間軸を集計キーにする groupby 月次データを年次に集計
rolling window 移動窓ごとに集計 3 年移動平均
transform 集計結果を元行に展開する ブロック平均を各県行に
apply グループに任意関数を適用 各ブロックの最大人口県を取得
filter グループ単位で条件に合う行のみ残す 人口 500 万超のブロックのみ
weighted average 重み付き平均 人口重み付き高齢化率
share / ratio 集計値を全体合計で割った割合 関東シェア 35.0%(2023 年度)
cumulative sum 累積和 人口上位県の累積シェア
rank グループ内順位 各ブロックでの人口順位
percentile 分位点(25%, 50%, 75%) ブロック内の Q1/Q3
unique / nunique 重複を除いた件数 グループ内のユニーク値数
groupby + agg pandas の標準集計パターン 最も多用される構文
MultiIndex 複数キー集計後の階層インデックス (Block, 性別) の組
reset_index MultiIndex を通常列に戻す 集計後の必須処理
observed=True 空のカテゴリ組合せを除外 大規模カテゴリで必須
dropna=False NaN もキーとして扱う 欠損を別グループとして集計
window function SQL のグループ内累積・差分 OVER (PARTITION BY)
aggregation level 集計の粒度 県 < ブロック < 全国
subtotal / grand total 小計・総計 ブロック計 + 全国計
cube / rollup 多次元集計(SQL の拡張) 複数キーの全組合せ小計
これらの用語は 「集計」という 1 つの操作のバリエーション として位置づけて理解するのがコツ。 SQL から pandas、 Polars、 DuckDB に至るまで、 用語と概念はほぼ共通している。 集計の語彙を増やすことが、 そのままチームでの議論の精度を上げる。
🔍 ケーススタディ:SSDSE-B-2026 を 3 段階で集計する完全ワークフロー
「集計」が単独の操作ではなく、 分析パイプラインの一部 であることを実感するために、 SSDSE-B-2026 を「読み込み → 前処理 → 集計 → 可視化 → 結論」の流れで通しで扱うケーススタディを示す。 ここでは 「地方ブロック別の高齢化進展度を分析する」 という現実的な問いに答える。
フェーズ 1:データ取り込みと前処理
SSDSE-B-2026 を pandas.read_csv で取り込む際の典型的なつまずきポイント:
文字コード :cp932 か utf-8 のどちらか。 SSDSE 公式は cp932 配布が多い。 encoding='cp932' を試して NaN が出るなら utf-8。
ヘッダー行 :1 行目が英語コード(A1101 など)、 2 行目が日本語ラベル(総人口など)、 3 行目以降がデータ。 普通に読むと 2 行目もデータ扱いになり集計が壊れる。 skiprows=[1] で日本語ラベル行を飛ばす。
型推定の事故 :県コードが「01」「02」と先頭ゼロを持つ場合、 pandas は数値に変換して「01」が「1」になる。 dtype={'Code': str} で文字列固定。
地方ブロック列の作成 :SSDSE には地方ブロック列がない。 都道府県名 → 地方ブロックの辞書を自分で作って map する必要がある。
フェーズ 2:集計の実行と検算
高齢化率=A1303(老年人口)/ A1101(総人口)。 これを地方ブロック別に集計する 3 つの方法:
集計方法
計算式
結果の意味
関東での値
単純平均 df.groupby('Block')['高齢化率'].mean()県の高齢化率を 7 県で平均 28.0%
人口加重平均 (grp['A1303'].sum() / grp['A1101'].sum())老年人口の合計を総人口の合計で割る 26.2%
中央値 df.groupby('Block')['高齢化率'].median()外れ値の影響を抑えた代表値 28.1%
結論 :同じ「関東の高齢化率」でも、 単純平均 28.0% / 加重平均 26.2% / 中央値 28.1%(2023 年度・実測値)と 1.8 ポイントもの差 がある。 政策議論ではこの違いを認識せずに数字を引用すると、 「東京(高齢化率 22.8%)の影響で関東は若い」と「群馬・茨城・栃木(高齢化率 30% 超)の高齢化が深刻」のどちらにも引用できてしまう。 必ず集計方法を明示 することが信頼性の基本。
フェーズ 3:可視化と結論
集計結果を表で示すだけでは政策担当者に届かない。 「順位 + 棒グラフ + 箱ひげ図」 のセットで可視化する。 棒グラフで「絶対的な順位」、 箱ひげ図で「ブロック内のばらつき」、 そして時系列折れ線で「変化のスピード」を示す。 この 3 つを 1 ページに収めることで、 集計値が 「水準・分散・速度」 の 3 軸で同時に伝わる。
可視化要素
伝える情報
読み手の典型的な反応
棒グラフ(地方ブロック × 高齢化率) 絶対的な順位、 ブロック間の差 「四国が一番高いのか」と直感的に把握
箱ひげ図(地方ブロック × 県別高齢化率) ブロック内のばらつき、 外れ値 「関東は東京が突出して若い」と発見
折れ線(2012→2023 の時系列) 変化のスピード 「東北・北海道の高齢化上昇が最速」と認識
ヒートマップ(地方 × 年) 時間と空間の二次元 「いつから加速したか」を一望
結論の書き方 :「四国は全国で最も高齢化が進んでおり(2023 年度で 34.4%・人口加重)、 2012→2023 の上昇幅も +6.3 ポイントと大きい(上昇幅の最大は東北 +7.1、 北海道 +7.0)。 一方で関東は東京(22.8%)と北関東 3 県(30% 超)の差が大きく、 ブロック単位の指標では構造が見えにくい。 政策設計は 都道府県単位 で行うべきで、 地方ブロック集計は傾向把握の補助 として位置づけるのが妥当」。
🔧 集計ツールの比較:pandas / SQL / Polars / DuckDB / Excel
同じ集計でも、 ツール選択でパフォーマンス・可読性・チーム共有のしやすさが大きく変わる。 SSDSE-B-2026 のような中規模データ(47 県 × 約 110 列)では pandas で十分だが、 業務システムでは状況に応じて使い分ける。 主要 5 ツールの比較を整理する。
ツール
主な記法
得意な場面
弱点
SSDSE での適性
pandas df.groupby(k).agg(...)柔軟な集計、 Jupyter での試行錯誤、 Python エコシステム連携 数 GB を超えるとメモリ不足。 遅い ◎ 第一選択
SQL SELECT k, SUM(v) FROM t GROUP BY kDB に既にあるデータの集計、 業務システム統合、 多人数共有 柔軟さで pandas に劣る。 デバッグ困難 ○ DB 取込時に有効
Polars df.group_by(k).agg(pl.col(v).sum())数 GB の大規模集計、 並列処理、 pandas より高速 学習コストあり、 周辺ライブラリが少ない △ SSDSE 規模ではオーバースペック
DuckDB SQL + Python 統合 duckdb.query(...) SQL の表現力 + メモリ効率、 CSV/Parquet 直接クエリ サーバ機能なし、 トランザクション弱 ○ パイプライン中段で有用
Excel ピボットテーブル機能、 SUMIF 非エンジニアとの共有、 即席集計 再現性低い、 数十万行で動作低下 △ 最終出力としては有効
同じ集計を 5 ツールで書き比べる(SSDSE-B-2026 の地方ブロック別人口合計)
ツール
コード
pandas df.groupby('Block')['A1101'].sum().reset_index()
SQL SELECT Block, SUM(A1101) AS total_pop FROM ssdse_b_2026 GROUP BY Block
Polars df.group_by('Block').agg(pl.col('A1101').sum().alias('total_pop'))
DuckDB duckdb.query("SELECT Block, SUM(A1101) FROM 'SSDSE-B-2026.csv' GROUP BY Block").to_df()
Excel ピボットテーブル:行=Block / 値=Sum of A1101
どのツールでも「キー(GROUP BY)」「集計関数(SUM)」「対象列(A1101)」の 3 要素が必要なのは共通。 ツールが変わってもこの 3 要素の構造は変わらないため、 集計の概念を理解すれば移植は簡単 。
ツール選択の判断フロー
データサイズ < 1GB かつ Python 環境 → pandas を使う(最も柔軟、 周辺ツール豊富)。
データが DB にある → SQL(GROUP BY)で集計、 結果だけ pandas に取り込む。
データサイズ > 数 GB、 並列処理したい → Polars に切り替える(pandas の 5〜10 倍速)。
CSV/Parquet を直接クエリしたい、 DB セットアップ嫌 → DuckDB が便利。
非エンジニアと共有する最終成果物 → 集計結果を Excel に貼り付け、 ピボットで微調整できる形で渡す。
SSDSE-B-2026 を扱う本コンペの規模では pandas が圧倒的に第一選択 。 ただし提出物を組織内で共有する段階では「pandas で集計 → Excel で見せる」というハイブリッド運用が現実的。
🧠 集計の本質を深掘りする 10 の論点
集計は一見シンプルだが、 実務では 「集計値だけで結論を出して炎上」 する事故が後を絶たない。 ここでは集計を扱う上で必ず押さえたい 10 の論点を、 SSDSE-B-2026 の具体例と共に整理する。 単なる pandas の操作を超え、 「集計値が社会的意思決定にどう影響するか 」まで考えるのが目的。
論点 1:集計は「圧縮」であり、 必ず情報を失う
SSDSE-B-2026 の 47 都道府県を 8 地方ブロックに集計すると、 個別の県名・分散・順位情報は すべて消える 。 集計値だけ見ていると、 「関東は人口が多い」までしか分からず、 「関東の中でも東京単独で 1400 万人」「群馬・栃木は 200 万人前後」という構造は見えない。 集計は 意思決定可能な粒度に丸める操作 であり、 同時に 原データへの不可逆な変換 であることを忘れてはいけない。
論点 2:集計関数の選択が結論を反転させる(Simpson's Paradox)
有名な Simpson's Paradox(シンプソンのパラドックス) は集計の落とし穴の代表例。 ある全体集団で A が B より優れていても、 集計の キーの選び方 次第で結論が逆転する。 有名な仮想例(年収は SSDSE-B-2026 にはない変数だが)では、 「全国平均年収」では業種 X が業種 Y を上回るが、 「地方ブロック別の年収」を見ると 全ての地方で業種 Y が業種 X を上回る 、 ということが起こりうる。 これは「業種ごとの地理的分布の偏り」が集計値を歪めるため。 集計は 必ず複数のキーで再集計して確認する のが鉄則。
論点 3:欠損値(NaN)の扱いで集計値が大きく変わる
pandas の集計関数(sum, mean)はデフォルトで NaN を 無視 する。 これは便利だが、 「集計対象列の半分が NaN だった」場合に 分母が変わってしまう という副作用がある。 SSDSE-B-2026 の特殊指標列(一部の県でのみ計測される項目)では、 mean を取ると「NaN を除いた県の平均」になり、 全国平均と誤解されやすい。 集計前に df.isna().sum() で欠損数を確認し、 必要なら fillna するか、 別カラムとして「観測数」を併記すること。
論点 4:単純平均と加重平均を取り違えない
「地方ブロックの平均高齢化率」を計算する場合、 単純平均(7 県の高齢化率を 7 で割る)と加重平均(人口で重み付け)は 違う値 になる。 SSDSE で関東の高齢化率を単純平均すると約 28% だが、 東京の人口が圧倒的に大きいので人口加重平均だと約 26% にずれる。 政策議論で「関東の高齢化率」と言われたとき、 どちらの定義かを確認するのが重要。 一般に「率」「割合」を集計するときは 加重平均が正解 のことが多い。
論点 5:集計の「キー」自体が分析の前提
SSDSE で「地方ブロック」を集計キーにするとき、 「沖縄を九州沖縄に含めるか、 沖縄単独にするか」「東日本・西日本の境界をどこに置くか」といった選択は、 分析結果を左右する。 集計キーは 暗黙ではなく明示 すべき。 多くの場合、 既存の標準分類(総務省の地方区分、 経済産業省のブロック分類)に従うのが安全だが、 分析目的に応じて再定義することもある。 集計キーの作成方法を レポートに必ず明記 し、 git で版管理すること。
論点 6:集計後の表は「読み手」が決まっている
集計結果を提示するときは、 誰がその表を読むか を先に決める。 経営層向けなら「シェア(%)」「前年比」を強調、 統計学者向けなら「標準偏差」「サンプル数」を併記、 一般読者向けなら「比喩」「順位」を強調する。 SSDSE-B-2026 を集計した同じ表でも、 自治体首長向けには「自県の全国順位」、 研究者向けには「変動係数(CV)」、 報道機関向けには「上位/下位 3 ブロック」を強調するのが効果的。
論点 7:集計値の「精度」は元データの精度に依存する
SSDSE-B-2026 の人口は住民基本台帳から取られているが、 推計誤差や年次差がある。 集計して 5 桁の数字(例:43,527 千人)を出しても、 元データに 1% の誤差があれば集計値も 1% の誤差を持つ。 「有効数字を増やすほど信頼性が上がる 」という誤解を避け、 集計結果を提示するときは 桁数を元データの精度に合わせる 。 SSDSE なら千人単位(4 桁)程度が現実的な有効数字。
論点 8:集計と「正規化」をワンセットで考える
集計値は「絶対量」と「正規化値」の 2 つの表現 を必ず併記すべき。 SSDSE-B-2026 の大学数を地方ブロックで sum しただけでは、 「関東が多い」までしか分からない。 だが「人口千人あたり大学数」「面積あたり大学数」を計算すると、 北海道や中国地方で意外に密度が高い、 という構造が浮かぶ。 集計レポートのテンプレートに「絶対量列 + 正規化列」を必ず入れる習慣をつけよう。
論点 9:時系列で集計値の変化を追う
単年の集計だけでは「水準」しか見えず、 「変化」が分からない。 SSDSE-B-2026 の 2012〜2023 年度パネルをそのまま使い、 「年 × 地方ブロック」で集計すれば、 「東北の人口減少ペース」「関東のシェア上昇」が定量化できる。 政策議論では 水準より変化のほうが重要 なことが多い。 時系列集計を加えるだけで、 同じデータから 3 倍の情報量が引き出せる。
論点 10:集計結果を「次の分析の入力」として設計する
集計はゴールではなく、 多くの場合は 次の分析の入力 。 SSDSE で地方ブロック集計を作ったら、 それを使って ① 棒グラフで可視化、 ② 他のブロック集計と merge、 ③ クラスタリングで「似たブロック」を発見、 ④ 回帰モデルの説明変数として投入、 と展開できる。 集計の段階で 「後工程が使いやすい形」 (reset_index 済、 列名は英数字、 NaN 処理済)にしておくと、 パイプライン全体の効率が上がる。
📜 歴史・背景
集計(aggregation)は統計学の起源そのものといっても過言ではない。 1662 年、 ジョン・グラント(John Graunt)はロンドン市の死亡記録を週次・年次で 集計 し『死亡表に関する自然的および政治的観察』を出版。 これが 近代統計学の最古の著作 とされる。 個別の死亡情報を「年齢階級」「死因」というキーで束ねたことが、 都市衛生政策の意思決定を可能にした。
19 世紀には、 フローレンス・ナイチンゲール(Florence Nightingale)がクリミア戦争の野戦病院死因を月別・原因別に集計し、 ローズダイアグラム(polar area chart) で可視化した。 「戦闘での死より、 衛生環境の不備による感染症死のほうが圧倒的に多い」という事実が、 集計と可視化の組み合わせで初めて社会に伝わった。
計算機時代に入ってからの集計の主役は SQL(1970 年代、 IBM)であり、 そこで GROUP BY 句が標準化された。 2000 年代以降の R の dplyr、 Python の pandas は SQL の集計セマンティクスを継承しつつ、 data frame という形でメモリ上の柔軟な集計を可能にした。 SSDSE のような中規模公的統計(数十 MB クラス)は、 pandas の groupby で十分快適に扱える時代に入った。
🚀 応用例・実務での使われ方
「集計」が実務でどう使われるか、 SSDSE-B-2026 を題材にした具体的なシナリオで見てみる。
シナリオ 1:地方創生レポートの作成
SSDSE-B-2026 の人口・出生数・転入転出から「地方ブロック別の人口流動表」を作る。 集計列:A1101(総人口)、 A4101(出生数)、 A5101(転入)、 A5102(転出)。 集計後の表をベースに、 「自然増減=出生数−死亡数」「社会増減=転入−転出」を算出し、 地方創生戦略の優先順位付けに使える。
シナリオ 2:高等教育インフラの偏在分析
列 E6102(大学数)・E6302(大学学生数)・A1101(総人口)を地方ブロックで集計。 「人口あたり大学学生数」を比較し、 東京一極集中の度合いを定量化(2023 年度実測では人口千人あたり大学学生数は関東 26.4 人でトップ、 最低は四国 13.1 人)。 集計値だけでなく シェア(%) と 人口比 の 2 つの観点で見るのがコツ。
シナリオ 3:医療資源の地域差
SSDSE の I 列(一般病院数 I510120・一般診療所数 I5102)を集計対象に、 ブロック別の「人口千人あたり一般診療所数」を算出。 単純合計だけでは「人口の多い関東が圧倒的」になるが、 正規化(人口で割る) をすると順位が入れ替わる(2023 年度実測:近畿 0.97、 中国 0.91、 四国・九州沖縄 0.89 > 関東 0.81)。
シナリオ 4:消費パターンの地域クラスタリング
SSDSE の L322 系列(家計の消費支出内訳:食料・住居・光熱・被服など)を地方ブロックで集計し、 ブロックごとの消費構成比を計算。 ここから k-means クラスタリング で「消費パターンが似たブロック群」を発見できる。 集計が機械学習の入力データを作るパイプラインの起点になる例。
🔄 似た概念との比較
「集計」と混同しやすい用語との比較表。 違いを明確にすることで使い分けの判断が早くなる。
観点 集計 似た用語 違い
行数の変化 行が 減る (圧縮) 結合(join)は行が 増える こともある 集計は縦方向の圧縮、 結合は横方向の拡張 キーの役割 グループを定義する列 結合キーは「同じ ID を持つ行をくっつける」 集計キーは「同じ値の行を束ねる」 典型関数 sum / mean / count / median merge / join 集計は集約関数、 結合はキーマッチ SQL 対応 GROUP BY + 集約関数 JOIN ... ON SQL でも別概念だが、 1 つのクエリで併用される SSDSE での例 47 県を 8 地方ブロックに圧縮 SSDSE の人口(A1101)と外部統計(例: 県民経済計算の県内総生産)を県コードで merge 集計は要約、 結合は変数追加 情報損失 あり (個票情報は失われる)なし(行数増・列数増のみ) 集計後は元データに戻れない
❓ よくある質問(FAQ)
Q. groupby と pivot_table の使い分けは?
A. groupby は 縦持ち の結果(MultiIndex も可)、 pivot_table は 横持ち のクロス表を作る。 行と列を両方カテゴリで切りたい(例:地方 × 高齢区分)ときは pivot_table が読みやすい。 縦持ちで後続処理(merge / plot)したいときは groupby が便利。
Q. 集計とリサンプリング(resample)の関係は?
A. resample は 時系列の時間軸 を集計キーにする groupby の特殊版。 SSDSE-B-2026 は年次の都道府県データなので resample は不要だが、 もし月次・四半期の時系列を年次に丸めるようなケースでは resample('Y') が便利(SSDSE-B-2026 の 2012-2023 パネルなら年度列での groupby で足りる)。
Q. NaN を含むキーで groupby するとどうなる?
A. pandas のデフォルト dropna=True では NaN を持つ行は 集計から除外 される。 「NaN もひとつのグループとして集計したい」なら groupby(key, dropna=False) を指定。 集計対象列の NaN とキー列の NaN を区別すること。
Q. 集計値を元データの各行に戻したい場合は?
A. transform を使う。 例:df['block_mean'] = df.groupby('Block')['A1101'].transform('mean') で「自県が所属するブロックの平均人口」を各行に展開できる。 偏差や標準化に必須。
Q. 巨大データで遅いときは?
A. 集計対象列を事前に astype('category') に変換、 不要列を drop、 groupby(observed=True) でメモリ削減。 さらに大規模なら Polars / DuckDB を検討。
✅ 実施前チェックリスト
□ 集計キー(groupby に渡す列)の 欠損 を確認したか? NaN は別グループになる。 □ 集計対象の列の データ型 を確認したか? 数値のはずが文字列になっていないか。 □ 集計関数(sum/mean/median/count)を 意識して選択 したか? □ 単純平均で済むか、 加重平均 が必要か判断したか? □ 集計後の シェア・割合 を計算するなら、 分母をどう決めるか考えたか? □ ばらつき情報(std, min, max)も同時に取得したか? □ カテゴリ列の 並び順 (地方ブロックの順序)を明示したか? □ 結果を reset_index() したか? 後続処理での MultiIndex 事故を回避。 □ 集計の結果を 表 + 図 の両方で確認したか? 一方だけだと見落とす。 □ 元データのバックアップ(df.copy())を取ったか? □ 集計後の行数が 想定通り か?(8 地方ブロックなら 8 行になっているか) □ 集計結果を CSV に書き出すとき、 文字コードは utf-8-sig にしたか? Excel で開く配慮。
📝 本ページまとめ — 「集計」を一言で
「集計(aggregation)」とは 個票レベルの観測値を、 グループ単位の要約統計量に変換する操作 。 SSDSE-B-2026 のような 47 都道府県データを「地方ブロック 8 つ」「年齢階級」「性別」などのキーで束ね、 sum / mean / count / median といった集約関数で 1 行に要約する。 pandas では df.groupby(key).agg(...) が中心ツールであり、 SQL の GROUP BY と 1 対 1 対応。
覚えるべきは 3 点 :① 集計後は 行が減る/元に戻れない 。 ② 集計関数の選び方(sum vs mean vs median)で 見える物語が変わる 。 ③ 加重平均が必要かどうかの判断。
📚 参考文献(集計・データ処理)
入門書
Wes McKinney『Python for Data Analysis 3rd Edition』O'Reilly:pandas 開発者本人による決定版。 集計の章が秀逸。
Hadley Wickham『R for Data Science』O'Reilly:Tidy Data 哲学。 集計の前後の整形を学ぶ。
『現場で使える!pandas データ前処理入門』翔泳社:日本語で集計を学ぶ最良の書。
中級書
Joe Celko『SQL for Smarties』Morgan Kaufmann:SQL の集計演算子を深く学ぶ古典。
Itzik Ben-Gan『T-SQL Window Functions』Microsoft Press:window 関数の決定版。
『データ指向アプリケーションデザイン』O'Reilly:大規模データの集計エンジニアリング。
論文・ガイドライン
Wickham (2014) "Tidy Data" Journal of Statistical Software:Tidy 哲学の原典論文。
統計局『公的統計の二次的利用に関するガイドライン』:SSDSE 等の利用ルール。
OECD『Statistical Disclosure Control』:集計データのプライバシー保護。
🚀 集計の高度パターン 8 つ
1. 加重集計(Weighted Aggregation)
# SSDSE-B-2026 で人口加重高齢化率
def weighted_avg(group, value_col, weight_col):
return (group[value_col] * group[weight_col]).sum() / group[weight_col].sum()
df['aging_rate'] = df['A1303'] / df['A1101']
result = df.groupby('Block').apply(lambda g: weighted_avg(g, 'aging_rate', 'A1101'))
2. ピボット + 集計
pv = df.pivot_table(
index='Block', columns='SSDSE-B-2026',
values='A1101', aggfunc='sum'
)
3. 移動平均(rolling)
# 都道府県別の人口 3 年移動平均
df_sorted = df.sort_values(['Prefecture', 'SSDSE-B-2026'])
df_sorted['MA3'] = df_sorted.groupby('Prefecture')['A1101'].transform(
lambda x: x.rolling(3).mean()
)
4. 累積集計(expanding)
df_sorted['cumulative_births'] = df_sorted.groupby('Prefecture')['A4101'].cumsum()
5. ランキング(rank)
df['pop_rank_in_block'] = df.groupby('Block')['A1101'].rank(ascending=False)
6. シフト(前年比)
df_sorted['pop_yoy'] = df_sorted.groupby('Prefecture')['A1101'].pct_change()
7. 多重 groupby
multi = df.groupby(['Block', 'SSDSE-B-2026']).agg({
'A1101': ['sum', 'mean', 'std'],
'A1303': 'sum',
})
8. カスタム集計関数
def gini_coef(values):
"""ジニ係数の計算"""
sorted_v = sorted(values)
n = len(sorted_v)
cumsum = sum((i+1) * v for i, v in enumerate(sorted_v))
return (2 * cumsum) / (n * sum(sorted_v)) - (n + 1) / n
block_gini = df.groupby('Block')['A1101'].apply(gini_coef)
✅ 集計チェックリスト(25 項目)
A. 設計段階(10 項目)
□ 集計の目的を 1 文で言えるか
□ 集計キーが意思決定の粒度と合っているか
□ 集約関数(sum/mean/median)を意識的に選んだか
□ 加重平均が必要か判断したか
□ 階層集計の必要性を検討したか
□ 集計レベルの感度を確認するか
□ シンプソンのパラドックスを警戒しているか
□ NaN の扱いを明示したか
□ カテゴリ列の順序を制御したか
□ 出力フォーマット(ワイド/ロング)を決めたか
B. 実行段階(8 項目)
□ 集計前のデータをバックアップしたか(df.copy())
□ 集計対象列の型を確認したか
□ count も同時に取得したか
□ std/min/max でばらつき情報を保存したか
□ groupby(observed=True) でメモリ削減したか
□ 集計結果の行数が想定通りか確認したか
□ reset_index() で MultiIndex を平坦化したか
□ 結果を中間ファイルに保存したか
C. 報告段階(7 項目)
□ 集計関数の種類を明記したか
□ サンプル数 n を併記したか
□ ばらつき情報を併記したか
□ 単位を明記したか
□ 表 + 図の両方で示したか
□ 解釈と限界を区別したか
□ CSV 出力時に utf-8-sig を使ったか
🏁 「集計」を 10 行で覚える
集計=個票をグループキーで束ね、 要約統計量に変換する操作。
pandas: df.groupby(key).agg(func)。 SQL: GROUP BY。
集約関数 sum/mean/median/count などで意味が変わる。
SSDSE-B-2026 で「47 県 → 8 地方ブロック」が典型例。
単純平均と加重平均を区別。 SSDSE では人口加重が必要なことが多い。
欠損は dropna=True/False で挙動が変わる。 必ず確認。
集計後は行が減り、 元データには戻れない。 必ず copy。
ばらつき情報(std/min/max)を mean と一緒に取る。
シンプソンのパラドックスを警戒。 複数レベルで感度分析。
transform で集計値を元の行に戻して標準化・偏差を計算。
🎓 次に読むべきページ :groupby 、 ピボットテーブル 、 相関分析 、 縦持ち・横持ち 。
📊 SSDSE-B-2026 で実践する集計パターン 10 種
SSDSE-B-2026 を題材に、 実務で頻出する集計パターンをコード付きで 10 種紹介。
パターン 1:都道府県 → 地方ブロック
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行)
都道府県 A1101(総人口)
北海道 5,092,000
東京都 14,086,000
沖縄県 1,468,000
…(全 47 行)
📋 コピー 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import pandas as pd
df = pd . read_csv ( 'data/raw/SSDSE-B-2026.csv' , encoding = 'cp932' , skiprows = [ 1 ], na_values = [ '-' ])
def _blk ( code ):
n = int ( str ( code ) . lstrip ( 'R' )) // 1000
if n == 1 : return '北海道'
if n <= 7 : return '東北'
if n <= 14 : return '関東'
if n <= 23 : return '中部'
if n <= 30 : return '近畿'
if n <= 35 : return '中国'
if n <= 39 : return '四国'
return '九州沖縄'
block_map = { p : _blk ( c ) for p , c in zip ( df [ 'Prefecture' ], df [ 'Code' ])}
df [ 'Block' ] = df [ 'Prefecture' ] . map ( block_map )
y2023 = df [ df [ 'SSDSE-B-2026' ] == 2023 ] # 単年に絞る(絞らないと 12 年分が混ざる)
result = y2023 . groupby ( 'Block' )[ 'A1101' ] . agg ([ 'sum' , 'mean' , 'std' , 'count' ])
print ( result )
📤 実行例(実測)
sum mean std count
Block
中国 7070000 1.414000e+06 9.092230e+05 5
中部 20749000 2.305444e+06 2.133179e+06 9
九州沖縄 14029000 1.753625e+06 1.385558e+06 8
北海道 5092000 5.092000e+06 NaN 1
四国 3578000 8.945000e+05 2.888004e+05 4
東北 8318000 1.386333e+06 5.213370e+05 6
近畿 21990000 3.141429e+06 2.898584e+06 7
関東 43527000 6.218143e+06 4.491161e+06 7
パターン 2:年度別集計
📋 コピー yearly = df . groupby ( 'SSDSE-B-2026' ) . agg ({
'A1101' : 'sum' , # 全国合計人口
'A4101' : 'sum' , # 全国合計出生数
})
print ( yearly )
📤 実行例(実測)
A1101 A4101
SSDSE-B-2026
2012 127589000 1037165
2013 127414000 1029763
2014 127238000 1003544
2015 127094745 1005668
2016 127044000 977177
2017 126920000 946095
2018 126748000 918361
2019 126555000 865212
2020 126146099 840808
2021 125500000 811611
2022 124946000 770750
2023 124353000 727269
パターン 3:高齢化率別の県数集計
📋 コピー df [ 'aging_rate' ] = df [ 'A1303' ] / df [ 'A1101' ]
df [ 'aging_class' ] = pd . cut ( df [ 'aging_rate' ], bins = [ 0 , 0.25 , 0.30 , 0.35 , 1.0 ],
labels = [ '若い' , '標準' , '高い' , '極高' ])
# 2023 年度に絞って「県数」を数える(パネルのままだと 12 年分の延べ数になる)
result = df [ df [ 'SSDSE-B-2026' ] == 2023 ] . groupby ( 'aging_class' , observed = True ) . size ()
print ( result )
📤 実行例(実測)
aging_class
若い 2
標準 10
高い 29
極高 6
dtype: int64
パターン 4:シェア計算(全国比)
📋 コピー y2023 = df [ df [ 'SSDSE-B-2026' ] == 2023 ]
total = y2023 [ 'A1101' ] . sum ()
y2023 [ 'pop_share' ] = y2023 [ 'A1101' ] / total * 100
print ( y2023 [[ 'Prefecture' , 'A1101' , 'pop_share' ]] . sort_values ( 'pop_share' , ascending = False ) . head ( 10 ))
📤 実行例(実測)
Prefecture A1101 pop_share
144 東京都 14086000 11.327431
156 神奈川県 9229000 7.421614
312 大阪府 8763000 7.046875
264 愛知県 7477000 6.012722
120 埼玉県 7331000 5.895314
132 千葉県 6257000 5.031644
324 兵庫県 5370000 4.318352
468 福岡県 5103000 4.103640
0 北海道 5092000 4.094795
252 静岡県 3555000 2.858797
パターン 5:地方ブロック内シェア
📋 コピー y2023 = df [ df [ 'SSDSE-B-2026' ] == 2023 ] . copy ()
y2023 [ 'block_pop_share' ] = y2023 . groupby ( 'Block' )[ 'A1101' ] . transform ( lambda x : x / x . sum () * 100 )
print ( y2023 [[ 'Prefecture' , 'Block' , 'A1101' , 'block_pop_share' ]] . sort_values ([ 'Block' , 'block_pop_share' ], ascending = [ True , False ]) . head ( 20 ))
📤 実行例(実測)
Prefecture Block A1101 block_pop_share
396 広島県 中国 2738000 38.727016
384 岡山県 中国 1847000 26.124470
408 山口県 中国 1298000 18.359264
372 島根県 中国 650000 9.193777
360 鳥取県 中国 537000 7.595474
264 愛知県 中部 7477000 36.035472
252 静岡県 中部 3555000 17.133356
168 新潟県 中部 2126000 10.246277
228 長野県 中部 2004000 9.658297
240 岐阜県 中部 1931000 9.306473
192 石川県 中部 1109000 5.344836
180 富山県 中部 1007000 4.853246
216 山梨県 中部 796000 3.836329
204 福井県 中部 744000 3.58
…(以下略)
パターン 6:年次変化(前年比)
📋 コピー df_sorted = df . sort_values ([ 'Prefecture' , 'SSDSE-B-2026' ])
df_sorted [ 'pop_growth' ] = df_sorted . groupby ( 'Prefecture' )[ 'A1101' ] . pct_change ()
print ( df_sorted [[ 'Prefecture' , 'SSDSE-B-2026' , 'A1101' , 'pop_growth' ]] . head ( 20 ))
📤 実行例(実測)
Prefecture SSDSE-B-2026 A1101 pop_growth
287 三重県 2012 1841000 NaN
286 三重県 2013 1833000 -0.004345
285 三重県 2014 1826000 -0.003819
284 三重県 2015 1815865 -0.005550
283 三重県 2016 1809000 -0.003781
282 三重県 2017 1801000 -0.004422
281 三重県 2018 1793000 -0.004442
280 三重県 2019 1783000 -0.005577
279 三重県 2020 1770254 -0.007149
278 三重県 2021 1756000 -0.008052
277 三重県 2022 1742000 -0.007973
276 三重県 2023 1727000 -0.008611
311 京都府 2012 2628000 NaN
…(以下略)
パターン 7:ランキング(ブロック内)
📋 コピー df [ 'rank_in_block' ] = df . groupby ([ 'Block' , 'SSDSE-B-2026' ])[ 'A1101' ] . rank ( ascending = False )
print ( df [ df [ 'rank_in_block' ] == 1 ][[ 'SSDSE-B-2026' , 'Block' , 'Prefecture' ]]) # 各ブロックの首位県
📤 実行例(実測)
SSDSE-B-2026 Block Prefecture
0 2023 北海道 北海道
1 2022 北海道 北海道
2 2021 北海道 北海道
3 2020 北海道 北海道
4 2019 北海道 北海道
.. ... ... ...
475 2016 九州沖縄 福岡県
476 2015 九州沖縄 福岡県
477 2014 九州沖縄 福岡県
478 2013 九州沖縄 福岡県
479 2012 九州沖縄 福岡県
[96 rows x 3 columns]
パターン 8:多重集計
📋 コピー multi = df . groupby ([ 'Block' , 'SSDSE-B-2026' ]) . agg ({
'A1101' : [ 'sum' , 'mean' , 'std' ],
'A1303' : 'sum' ,
'A4101' : [ 'sum' , 'mean' ],
})
print ( multi . head ())
📤 実行例(実測)
A1101 A1303 A4101
sum mean std sum sum mean
Block SSDSE-B-2026
中国 2012 7517000 1503400.0 935340.205487 2014000 62278 12455.6
2013 7491000 1498200.0 934712.362174 2076000 61921 12384.2
2014 7463000 1492600.0 934568.510062 2138000 59696 11939.2
2015 7438037 1487607.4 935398.498887 2154918 59813 11962.6
2016 7412000 1482400.0 935221.524560 2218000 57793 11558.6
パターン 9:加重平均(人口加重高齢化率)
📋 コピー def weighted_aging ( group ):
return ( group [ 'A1303' ] . sum () / group [ 'A1101' ] . sum ())
block_aging = df [ df [ 'SSDSE-B-2026' ] == 2023 ] . groupby ( 'Block' ) . apply ( weighted_aging )
print ( block_aging . sort_values ( ascending = False ))
# 2023年度: 四国 0.344 > 東北 0.335 > 北海道 0.330 > … > 関東 0.262
📤 実行例(実測)
Block
四国 0.343767
東北 0.335417
北海道 0.330126
中国 0.320085
九州沖縄 0.305866
中部 0.296930
近畿 0.292087
関東 0.261677
dtype: float64
パターン 10:ピボットテーブル
📋 コピー import os
os . makedirs ( 'outputs' , exist_ok = True ) # 書き出し先を先に作る
pv = df . pivot_table (
index = 'Block' ,
columns = 'SSDSE-B-2026' ,
values = 'A1101' ,
aggfunc = 'sum' ,
)
print ( pv )
pv . to_csv ( 'outputs/block_year_pop.csv' , encoding = 'utf-8-sig' )
📤 実行例(実測)
SSDSE-B-2026 2012 2013 2014 ... 2021 2022 2023
Block ...
中国 7517000 7491000 7463000 ... 7198000 7137000 7070000
中部 21613000 21570000 21513000 ... 21011000 20886000 20749000
九州沖縄 14558000 14528000 14491000 ... 14174000 14108000 14029000
北海道 5465000 5438000 5410000 ... 5183000 5140000 5092000
四国 3930000 3903000 3875000 ... 3659000 3620000 3578000
東北 9158000 9103000 9046000 ... 8519000 8426000 8318000
近畿 22695000 22652000 22596000 ... 22195000 22094000 2199000
…(以下略)
📚 ケーススタディ:集計が政策・経営に与えた影響 5 例
事例 A:日本の高齢化対策
国民健康・栄養調査の個票を 47 都道府県別・年齢階級別に集計 し、 「高齢者の食事減塩実態 」を把握。 都道府県別の差を見出し、 重点指導都道府県を選定。 集計が政策ターゲティングを可能にした例。
事例 B:地方創生交付金の算定
SSDSE のような公的統計を地方ブロック別に集計し、 「人口減少率」「若年世帯比率」を指標化。 交付金配分の根拠データに。 集計関数の選択(単純合計 vs 加重平均)で配分が変わるため、 政治的に重要。
事例 C:銀行の信用ポートフォリオ管理
数百万件の融資データを業種別・地域別・与信スコア帯別に集計。 集計値からポートフォリオの偏り(産業集中リスク・地域集中リスク)を発見し、 与信方針を調整。
事例 D:選挙の出口調査
数万人の投票後アンケートを年代別・地域別・支持政党別に集計。 メディアの開票速報で「年代別投票傾向」を可視化。 集計の 速さ と 正確さ が勝負。
事例 E:プロスポーツの戦術分析
サッカー・野球の選手別・対戦相手別・球種別の成績を集計。 「このピッチャーは右打者に弱い 」のような特性を発見。 集計が選手起用と戦術を変えた。
🗺 概念マップ
「aggregation」を中心とした関連概念マップ。
集計 (Aggregation)
クリーニング (前段)
フィルタ / グループ
結合 (join / merge)
可視化 / モデル投入
SQL GROUP BY
rolling / window 集計
🗺 概念マップ:集計の位置づけ
[CSV/Excel/DB] ──read_csv──> [DataFrame (個票)]
│
┌───────┴───────┐
cleanse join
│ │
└──── groupby ────► [集計テーブル] ──► [可視化] / [モデル]
(平均/合計/件数)
🔗 隣接手法への橋渡し
「集計」はデータ準備の中間工程。 生データを縮約して比較可能な形にする橋渡し的な処理。 上流・並列・下流の隣接概念とセットで理解する。
上流(前提・基盤) : データクレンジング — 集計の前提工程。 欠損・外れ値・型を整えないと集計値が嘘をつく。 ここを理解しないと「集計」の出発点が見えない。
並列(同レベルの代替・補完) : ピボットテーブル — 集計の表形式表現。 Excel/pandas で同じ概念を別表現。 「集計」と並んで検討すべき選択肢。
下流(発展・応用) : 可視化 — 集計値をグラフに落として読み取る次工程。 棒グラフ・ヒートマップ・地図。 「集計」を理解した次のステップ。
この上流→「集計」→下流の流れを意識して学ぶと、 周辺領域への橋渡しがスムーズになる。 「🌐 関連手法・派生」セクションに更に広いネットワークがある。
🌳 手法選択フロー
「集計」を全体平均で済ますか、 グループ別代表値や順序統計量、 サブグループ分解まで踏むかは、 必要な代表値・関数の対称性・Simpson's paradox 懸念の 3 軸で決める。 集計の粒度を誤ると平均的に正しいが個別には誤った結論になる。
分岐 1(前提条件・データ粒度) : 「グループ別の代表値が欲しいか?」 Yes → groupby + mean/median/sum、 No → 全体統計量で十分。 都道府県別・年代別・カテゴリ別など最も知りたい切り口を最初に確定する。
分岐 2(集計関数の対称性) : 「集計関数は対称か非対称か?」 平均/合計は対称(外れ値に弱い)、 中央値・四分位・上位 10% は順序統計量(外れ値に強い)。 分布の歪みが大きいデータでは中央値併記を推奨。
分岐 3(異質性・Simpson's paradox) : 「サブグループで結果が逆転しうるか?」 Yes → グループ別集計を必ず併記、 No → 全体集計のみで可。 男女別・年齢別・地域別での再集計を一度試すこと。
分岐 4(欠損・ゼロ件セル) : 「集計セルにゼロ件や NaN が混じるか?」 Yes → min_count/fillna/件数併記で対応、 No → 通常集計。 件数が極端に少ないセル (n<5) を信用しない。
分岐 5(運用・更新頻度) : 「定常運用で繰り返し集計するか?」 Yes → BI ツール/dbt/cron で自動化、 No → 一度限りなら notebook で十分。 自動化時はテスト・スキーマ変更検知も合わせて設計する。
フローは出発点であって絶対解ではない。 領域知識・データ特性・運用制約を加えて最終判断する。 迷ったときは「🔗 隣接手法への橋渡し」と「🌐 関連手法・派生」を見直し、 単一の手法に固執しないこと。
🧭 解説を深める:集計は「非可逆圧縮」— 捨てた情報を測り、再集計の可否を見極める
本文では「集計すると行数が減り、 元データに戻れない」ことを繰り返し注意した。 このセクションではさらに一歩進めて、 ①捨てた情報の量を数値で測る方法 (分散の分解)と、 ②集計結果をもう一度集計してよいかを判定する枠組み (集約関数の可分解性)という、 本文では扱わなかった 2 つの角度から集計を捉え直す。 数値はすべて SSDSE-B-2026(2023 年度・47 都道府県)から Python で実際に計算した実測値である。
💡 直感 — 「どれだけ情報を捨てたか」は分散の分解で測れる
集計は画像でいう 非可逆圧縮(JPEG) に似ている。 47 県 → 8 ブロックに圧縮すると細部(県ごとの違い)は消えるが、 「どれだけ消えたか」は感覚ではなく数値で測れる。 鍵は分散の分解:
全体のばらつき(全平方和)= グループ間のばらつき + グループ内のばらつき
グループ間 ÷ 全体 の比率(相関比 η²、 分散分析 と同じ量)が、 集計キーが保持できた情報の割合 になる。 実測すると、 2023 年度の県別高齢化率(A1303/A1101)を 8 地方ブロックで分解した場合、 全平方和 512.6 のうちブロック間は 201.5 で η² = 0.393 。 つまり「地方ブロック平均」という集計表は、 高齢化率の県間のばらつきの 約 39% しか表現できておらず、 残り約 61% はブロック内の県差として圧縮時に消えている 。 総人口 A1101 でも η² = 0.372 と同水準。 「地方ブロック」という直感的に自然な括りでも、 情報の過半は捨てているという事実は、 集計表を読むときの謙虚さにつながる。 グループ内標準偏差を併記すれば(例:高齢化率のブロック内標準偏差は四国 1.66 ポイント〜九州沖縄 3.67 ポイント)、 「どのブロックの平均値が均質で信頼できるか」まで示せる。
⚠️ 落とし穴(重要) — 集計後の相関は個票の相関の代わりにならない(生態学的誤謬)
本文の落とし穴(平均の平均・欠損・Simpson's paradox)に加え、 相関係数を集計データで計算し直すと値が別物になる という罠がある。 SSDSE-B-2026(2023 年度)での実測例:
符号が反転する例 :高齢化率と人口 10 万人あたり一般診療所数(I5102/A1101)の相関は、 47 都道府県レベルでは r = +0.19 。 ところが 8 地方ブロックに(分子・分母を別々に sum して)集計してから計算すると r = −0.16 と 符号ごと反転 する。
大きさが縮む例 :高齢化率と人口千人あたり出生数(A4101/A1101)は、 47 県レベルで r = −0.615、 8 ブロック集計後は r = −0.511 に縮む。
集計単位を粗くしたときに相関が増幅・縮小・反転しうることは Robinson(1950)が「生態学的相関」として指摘した古典的問題で、 生態学的誤謬 (ecological fallacy:集団レベルの関係を個体レベルに読み替える誤り)と呼ばれる。 教訓は 2 つ。 ①相関・回帰は原則として最も細かい粒度(ここでは 47 県の個票)で計算する 。 ②集計値どうしの相関を報告するときは「これは地方ブロック単位の相関であり、 都道府県単位・個人単位の関係を意味しない」と粒度を明記する。 どの粒度の切り方(境界線)を選ぶかで結果が変わる現象は地理学で MAUP (可変地区単位問題)とも呼ばれ、 集計キーの設計自体が分析結果を左右することを示している。
🚀 発展 — 集約関数の「可分解性」:再集計できる関数・できない関数
「県 → ブロック」の集計結果から、 さらに「ブロック → 全国」を計算してよいか? 答えは 集約関数の種類によって Yes / No が分かれる 。 データキューブの古典(Gray ら、 1997)は集約関数を 3 種類に分類した:
分配的(distributive) :sum・count・min・max。 部分集計をそのまま同じ関数で束ね直せば全体と一致する。 「ブロック別人口合計を sum すれば全国人口」— 再集計は常に安全。
代数的(algebraic) :mean・var・std。 そのままでは再集計不可だが、 補助情報(sum と count)を持ち回れば復元可能 。 実測:ブロック別平均人口をさらに単純平均した「平均の平均」は 277.6 万人で、 47 県の真の平均 264.6 万人と 約 13 万人ずれる (ブロックの県数 1〜9 が異なるため)。 sum ÷ count で計算し直せば厳密に一致する。
全体的(holistic) :median・mode・分位点。 どんな固定サイズの補助情報でも厳密復元は不可能 。 実測:47 県の総人口の全国中央値は 154.9 万人(鹿児島県)、 一方「ブロック別中央値の中央値」は 154.7 万人。 今回はたまたま近いが、 一致する保証はどこにもなく、 グループ構成次第で大きく外れる。
この分類は分散処理(MapReduce・Spark・DuckDB の並列集計)の設計原理そのものでもある。 各ワーカーが部分集計を返して束ねられるのは分配的・代数的関数まで。 holistic な分位点は t-digest などの近似スケッチ で妥協するのが実務の定石(近似カウントの HyperLogLog は「🔬 発展トピック」参照)。 BI ダッシュボードで「集計済みテーブルからさらに集計」する場面では、 その列が sum 由来か mean 由来か median 由来かを必ず確認する 癖をつけたい。
🔗 関連ページ
groupby — 集計の中核 API。 可分解性を意識した agg(['sum','count']) の書き方へ。
分散分析(ANOVA) — 本セクションの「群間 ÷ 全体」分解を検定の枠組みに発展させたもの。
分散 / 標準偏差 — 集計で消える「グループ内ばらつき」を残すための付帯統計量。
相関係数 — 生態学的誤謬の主戦場。 粒度を変えて相関を再計算する習慣を。
平均 / 中央値 — 代数的関数と全体的関数の代表例。
ピボットテーブル — 2 軸集計。 マージン(小計)行が分配的関数でしか厳密に成立しない理由が本セクションで分かる。
シンプソンのパラドックス・生態学的誤謬の専用ページは現在未収録(本ページ「⚠️ 落とし穴」と本セクションが該当解説)。