論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
集約
Aggregation
データ処理

🔖 キーワード索引

本ページのトピックを 1 タップで移動できます。 「集約(aggregation)」— 日本語では「集計」とも呼ばれ、本ページでは同義語として両方の表記を用いる — を学ぶうえで押さえたい論点はすべてここに集約しました。

30秒で結論文脈ボックス直感で掴む数式・定義記号の意味実値で計算Python実装落とし穴関連手法関連用語グループ教材概念マップチェックリスト

aggregation」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「aggregation」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

aggregation統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「aggregation の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

バラバラのデータを束ねる作業です。

データの全体像をパッと見るために使います。

部活のメンバーを学年ごとに分けるようなものです。

集約のやり方と注意点を学びます。

複数行のデータを groupby などのキーで束ね、 合計・平均・件数などの要約統計量に変換する操作。

📍 あなたが今見ているもの

🍰 まずはやさしく

分析の準備をするためのステップです。

データを使いやすい形に変えるために使います。

スマホのアプリで、日ごとの利用時間をまとめる時に似ています。

分析の流れの中でどこに位置するかを学びます。

分野:データエンジニアリング(前処理 → 集計 → 可視化 → モデル化のうち、 集計フェーズ)。 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 タイプある:

大事なのは、 「合計」と「平均」と「件数」で見える物語がまったく違う ということ。 たとえば「関東は人口合計で日本一(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')

📐 数式・定義

🍰 まずはやさしく

データを計算して1つの値にするルールです。

正確に数値をまとめるために使います。

テストの点数を合計して、平均点を出す計算と同じです。

集約で使う代表的な計算式について学びます。

グループ \(g\) に属する観測値の集合を \(S_g = \{x_i : i \in g\}\)、 その要素数を \(n_g\) とする。 代表的な集計関数は次の通り。

$$ \text{sum}(g) = \sum_{i \in g} x_i, \qquad \text{mean}(g) = \frac{1}{n_g}\sum_{i \in g} x_i $$ $$ \text{count}(g) = n_g, \qquad \text{var}(g) = \frac{1}{n_g - 1}\sum_{i \in g}(x_i - \text{mean}(g))^2 $$ $$ \text{min}(g) = \min_{i \in g} x_i, \qquad \text{max}(g) = \max_{i \in g} x_i $$

複数キーでの集計(多段 groupby)は、 集合の 分割を入れ子にする操作と等しい。 たとえば「地方ブロック × 性別」で人口を集計する場合:

$$ A_{b,s} = \sum_{i : \text{block}(i)=b,\ \text{sex}(i)=s} \text{pop}_i $$

割合(シェア)の計算は集計値を全体合計で割る正規化操作:

$$ \text{share}(g) = \frac{\text{sum}(g)}{\sum_{g'} \text{sum}(g')} \times 100\ [\%] $$

「集計」と双対の概念に 結合(join)がある。 集計が 「縦方向の圧縮」 なら、 結合は 「横方向の拡張」。 多くの分析パイプラインは read → join → groupby → agg の順で組まれる。

📐 集計実例:SSDSE-B-2026 の地方ブロック別 延べ宿泊者数

SSDSE-B-2026 の延べ宿泊者数 G7101 を地方ブロック別に sum で集計し、 シェアと 1 人当たり宿泊数を計算した実例(2023 年・実測値)。

地方延べ宿泊者数合計(百万人泊)全国シェア(%)1 人当たり宿泊数(泊/人)
関東153.930.83.5
近畿99.519.94.5
中部80.916.23.9
九州沖縄67.413.54.8
北海道32.86.66.4
東北32.06.43.8
中国22.24.43.1
四国11.22.23.1

「合計」で集計すると関東のシェアが最大(30.8%)だと分かりますが、 「1 人当たり」に正規化すると観光地の北海道(6.4 泊/人)が関東(3.5 泊/人)を上回り、 順位が入れ替わります。 集計関数・正規化の選択で見える物語が変わる典型例です。

🔬 数式を言葉で読み解く

記号意味
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 問

  1. 基本集計:SSDSE-B-2026 で「47 都道府県の総人口(A1101)」を地方ブロック別に sum、 mean、 median で集計せよ。 結果がどう違うか比較。
  2. 加重平均:「都道府県別の高齢化率」を、 人口で加重した「地方ブロックの加重平均高齢化率」を計算せよ。 単純平均との差を 200 字で考察。
  3. 多重集計:1 つの agg() で、 人口の sum + 出生数の mean + 大学数の max を同時に集計せよ。
  4. 2 軸集計:地方ブロック × 高齢区分(若い/標準/高い)でクロス集計(人口の sum)。
  5. transform 活用:各県の人口を「自県が所属する地方ブロックの平均人口」で標準化せよ。
  6. カスタム関数:地方ブロックごとに「人口最大の県名」を返す集計関数を定義せよ。
  7. 欠損対処:欠損のある列を集計する際の挙動を dropna=True/False で比較。
  8. 並び順制御:地方ブロックの集計結果を「北海道→東北→…」の順で出力するコードを書け。
  9. ピボット表:地方ブロック × 年度の 2 軸で「平均人口」のクロス表を作成(pivot_table 使用)。
  10. 感度分析:集計関数を 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 の groupByKeyreduceByKey

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)

操作pandasSQLExcelR (dplyr)
グループ化df.groupby('k')GROUP BY kピボットテーブルgroup_by(k)
合計.sum()SUM(x)SUMIFsummarise(sum(x))
平均.mean()AVG(x)AVERAGEIFsummarise(mean(x))
中央値.median()PERCENTILE_CONT(0.5)MEDIANsummarise(median(x))
カウント.size()COUNT(*)COUNTIFsummarise(n())
フィルタdf[cond]WHEREフィルタ機能filter()
グループ後フィルタ.filter()HAVING手動filter()
行に展開.transform()OVER (PARTITION BY)VLOOKUPmutate(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 合計)。

地方県数総人口平均人口加重高齢化率人口最大県
北海道1509 万509 万33.0%北海道
東北6832 万139 万33.5%宮城県
関東74,353 万622 万26.2%東京都
中部92,075 万231 万29.7%愛知県
近畿72,199 万314 万29.2%大阪府
中国5707 万141 万32.0%広島県
四国4358 万89 万34.4%愛媛県
九州沖縄81,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, ...
1
2
3
4
5
6
7
8
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 形式を使う。

1
2
3
4
5
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 で定義し、 年度ごとに集約。 ばらつきの「相対的大きさ」を観察。

1
2
3
4
5
6
7
8
9
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 表示する。

1
2
3
4
5
6
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 年度の実測値(万人)で示す。

地方ブロック 含まれる都道府県(数) 総人口(万人) 平均人口(万人) 全国シェア(%)
北海道1509509.24.1
東北6832138.66.7
関東74353621.835.0
中部92075230.516.7
近畿72199314.117.7
中国5707141.45.7
四国435889.42.9
九州沖縄81403175.411.3
全国合計4712435264.6100.0

表から:関東ブロック単独で全国人口の約 35% を占める(4353/12435)。 これは個別の 47 行を眺めるだけでは見えにくい構造。 集計が「視点を変える」ことが分かる典型例。

同様に 出生数 A4101 を集計すれば「東日本 vs 西日本での子ども数の偏り」、 大学数 E6102 を集計すれば「高等教育インフラの地域偏在」が浮かび上がる。

補助計算:65 歳以上人口比(高齢化率)の地方ブロック平均

SSDSE-B-2026 の列 A1303(65 歳以上人口)/A1101(総人口)から県別高齢化率を計算し、 地方ブロックごとに単純平均をとると下表のようになる(2023 年度・実測値)。

地方ブロック 高齢化率の平均 (%) 最小県 (%) 最大県 (%)
北海道33.033.033.0
東北34.529.239.1
関東28.022.831.0
中部31.325.733.9
近畿30.327.034.2
中国33.030.135.4
四国34.632.536.3
九州沖縄31.523.834.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: データ準備 (合成、 多様な整数)

i12345
$x_i$35827

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
合計026

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 的な集計の核心です。 「合計」ボタンでは点が多い/値が大きいグループの棒が高くなり、 「件数」ボタンでは値の大小と無関係に 点の個数だけ が棒の高さになります。 同じ配置でも、 関数を変えるだけで棒の順位が入れ替わることを確認してください。

⚠️ よくある落とし穴(このウィジェットで再現できる)

🚀 発展

実データでは、 このトグルが 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:集計結果を元の行に戻す

1
2
3
4
5
# 各県の人口を「自県が所属する地方ブロック総人口」で割って、 ブロック内シェアを計算
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 点に圧縮する操作であり、 当然ながら個別の県名・各点の散らばりは失われる。 集計値だけを見ていると、 「東京単独で外れ値的に大きい」といった構造を見落としかねない。 集計を行う 前後を必ず可視化で対比するのが、 データ分析の基本作法。

散布図:集計前の47都道府県分布
図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,0925142,8971,68133.0
東北8,3188704,6572,79033.5
関東43,5274,81027,32711,39026.2
中部20,7492,42312,1666,16129.7
近畿21,9902,51213,0536,42329.2
中国7,0708363,9722,26332.0
四国3,5783941,9551,23034.4
九州沖縄14,0291,8127,9274,29130.6
全国124,35314,17173,95436,22929.1

読み方:人口の 絶対量では関東が圧倒的(全国の 35.0%)。 高齢化率(人口加重)では 四国(34.4%) が最も高く、 関東は逆に最低(26.2%)。 集計関数を sum から比率に変えるだけで、 同じデータから正反対の地域構造が見えるのが分かる(2023 年度・実測値)。

観点 2:教育・労働列の集計と「正規化」の重要性

SSDSE-B-2026 の E 列(教育)や F 列(労働)を地方ブロックで集計すると、 絶対量はほぼ人口に比例してしまう。 そこで「人口で割る」「シェアで表す」といった 正規化が必須になる。 たとえば大学数 E6102 を集計するだけでなく、 「人口千人あたりの大学数」を計算することで、 「地方別の高等教育インフラ密度」が見える(下表は 2023 年度・実測値)。

地方ブロック 大学数 (校) 人口 (千人) 千人あたり大学数 大学シェア (%)
北海道375,0920.00734.6
東北528,3180.00636.4
関東26743,5270.006133.0
中部14420,7490.006917.8
近畿15821,9900.007219.5
中国547,0700.00766.7
四国183,5780.00502.2
九州沖縄8014,0290.00579.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,3181,3865219142,2640.38
関東43,5276,2184,4911,89714,0860.72
中部20,7492,3052,1337447,4770.93
近畿21,9903,1412,8998928,7630.92
九州沖縄14,0291,7541,3867955,1030.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 年移動平均 (関東)
201542,9958,98333.842,856
201743,3338,85034.143,168
201943,6278,69534.543,481
202143,5618,51934.743,614
202343,5278,31835.043,541

読み方(2012〜2023 年度・実測値、 単位:千人。 移動平均は年次系列から計算):関東は 2012→2023 で +874 千人(ただし 2020 年度の 43,653 千人をピークに微減に転じている)、 東北は −840 千人(明確な減)。 関東/全国シェアは 33.4% → 35.0% と着実に上昇 = 一極集中の進行が定量化できる。 単年集計(観点 1〜3)では見えない「変化のスピード」は、 時系列集計でのみ捉えられる。

🛠 集計設計の意思決定フレーム

「どの列をどう集計するか」は、 機械的に決まらない設計判断。 ここでは 5 ステップの意思決定フレームを示す。 SSDSE-B-2026 を集計する前に、 必ずこの順序でレビューすると、 「集計したけど分析が刺さらない」事故を回避できる。

  1. ステップ 1:分析の問い(research question)を 1 文で書く。 例:「東日本と西日本で、 高等教育インフラの密度に差があるか?」「地方別の人口減少ペースを比較する」。 問いがないと「キー」「集計関数」「正規化」がすべて恣意的になる。
  2. ステップ 2:集計キーを 1 つに絞る(あるいは 2 軸交差にする)。 SSDSE では「都道府県(47)」「地方ブロック(8)」「年(時系列)」「年齢区分(3)」が代表的キー。 粒度が細かすぎる(47 県)と集計の効果が薄く、 粗すぎる(東西 2 分)と情報損失が大きい。 8 地方ブロックが「意思決定の粒度」と「統計的安定性」のバランス点。
  3. ステップ 3:集計関数を選ぶ(sum / mean / median / std)。 絶対量を見たいなら sum、 県あたり水準なら mean、 外れ値の影響を抑えたいなら median、 ばらつきを併記したいなら std。 ヒストグラムで分布形を確認してから決める。
  4. ステップ 4:正規化が必要か判断。 「人口当たり」「面積当たり」「世帯当たり」など、 分母を決めて比率に変えると、 大きさの効果を取り除いた純粋な構造が見える。 SSDSE の E 列・F 列・H 列はほぼ常に正規化が必要。
  5. ステップ 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']) を癖にする

🗺 概念マップ

「aggregation」を中心とした関連概念マップ。

集計 (Aggregation) クリーニング (前段) フィルタ / グループ 結合 (join / merge) 可視化 / モデル投入 SQL GROUP BY rolling / window 集計

🗺 概念マップ:集計の位置づけ

[CSV/Excel/DB] ──read_csv──> [DataFrame (個票)]
                                  │
                          ┌───────┴───────┐
                       cleanse        join
                          │             │
                          └──── groupby ────► [集計テーブル] ──► [可視化] / [モデル]
                                              (平均/合計/件数)
    

🔗 隣接手法への橋渡し

「集計」はデータ準備の中間工程。 生データを縮約して比較可能な形にする橋渡し的な処理。 上流・並列・下流の隣接概念とセットで理解する。

この上流→「集計」→下流の流れを意識して学ぶと、 周辺領域への橋渡しがスムーズになる。 「🌐 関連手法・派生」セクションに更に広いネットワークがある。

🌳 手法選択フロー

「集計」を全体平均で済ますか、 グループ別代表値や順序統計量、 サブグループ分解まで踏むかは、 必要な代表値・関数の対称性・Simpson's paradox 懸念の 3 軸で決める。 集計の粒度を誤ると平均的に正しいが個別には誤った結論になる。

  1. 分岐 1(前提条件・データ粒度): 「グループ別の代表値が欲しいか?」 Yes → groupby + mean/median/sum、 No → 全体統計量で十分。 都道府県別・年代別・カテゴリ別など最も知りたい切り口を最初に確定する。
  2. 分岐 2(集計関数の対称性): 「集計関数は対称か非対称か?」 平均/合計は対称(外れ値に弱い)、 中央値・四分位・上位 10% は順序統計量(外れ値に強い)。 分布の歪みが大きいデータでは中央値併記を推奨。
  3. 分岐 3(異質性・Simpson's paradox): 「サブグループで結果が逆転しうるか?」 Yes → グループ別集計を必ず併記、 No → 全体集計のみで可。 男女別・年齢別・地域別での再集計を一度試すこと。
  4. 分岐 4(欠損・ゼロ件セル): 「集計セルにゼロ件や NaN が混じるか?」 Yes → min_count/fillna/件数併記で対応、 No → 通常集計。 件数が極端に少ないセル (n<5) を信用しない。
  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 年度)での実測例:

集計単位を粗くしたときに相関が増幅・縮小・反転しうることは Robinson(1950)が「生態学的相関」として指摘した古典的問題で、 生態学的誤謬(ecological fallacy:集団レベルの関係を個体レベルに読み替える誤り)と呼ばれる。 教訓は 2 つ。 ①相関・回帰は原則として最も細かい粒度(ここでは 47 県の個票)で計算する。 ②集計値どうしの相関を報告するときは「これは地方ブロック単位の相関であり、 都道府県単位・個人単位の関係を意味しない」と粒度を明記する。 どの粒度の切り方(境界線)を選ぶかで結果が変わる現象は地理学で MAUP(可変地区単位問題)とも呼ばれ、 集計キーの設計自体が分析結果を左右することを示している。

🚀 発展 — 集約関数の「可分解性」:再集計できる関数・できない関数

「県 → ブロック」の集計結果から、 さらに「ブロック → 全国」を計算してよいか? 答えは 集約関数の種類によって Yes / No が分かれる。 データキューブの古典(Gray ら、 1997)は集約関数を 3 種類に分類した:

この分類は分散処理(MapReduce・Spark・DuckDB の並列集計)の設計原理そのものでもある。 各ワーカーが部分集計を返して束ねられるのは分配的・代数的関数まで。 holistic な分位点は t-digest などの近似スケッチで妥協するのが実務の定石(近似カウントの HyperLogLog は「🔬 発展トピック」参照)。 BI ダッシュボードで「集計済みテーブルからさらに集計」する場面では、 その列が sum 由来か mean 由来か median 由来かを必ず確認する癖をつけたい。