論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
名義尺度
Nominal Scale
基礎統計

🔖 キーワード索引

#カテゴリ変数#Stevens尺度#順序なし#ダミー変数#one-hot#頻度

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

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

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

💡 30秒で分かる結論

🍰 まずはやさしく

名義尺度は、区別のためのラベルのようなものです。

データの種類を分けるために使います。

血液型や性別などがこの例にあたります。

ここでは、できる計算やグラフについて読みます。

名義尺度:区別のみ可能な尺度(性別、 血液型など)

📍 文脈ボックス

🍰 まずはやさしく

これは統計の基礎となる考え方です。

データ分析の基本を身につけるために使います。

都道府県の名前などを分析する時に役立ちます。

定義から実装までを順番に学んでいきましょう。

この用語は 基礎統計 カテゴリに属します。 関連する別称・略号:(なし)

論文・実務レポートで 名義尺度 が登場したら、 まず本ページの「30秒で分かる結論」と「直感で掴む」を読めば、 その文脈で何を言っているか把握できます。

本ページでは「nominal scale」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。

「nominal scale」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む

🍰 まずはやさしく

名義尺度は、名前を付けるだけのデータです。

順序や大きさを比べない時に使います。

好きな色や出身地などがこの例にあたります。

数え方や分析のやり方を具体的に見ていきましょう。

「血液型 A・B・O・AB」「都道府県名」「色」── これらの値は単なるラベルで、 「A > B」とは言えない。 これが 名義尺度。 順序尺度 (満足度 1〜5) や間隔尺度 (温度 °C) との違いを意識すること。 平均は無意味、 頻度・最頻値だけが意味を持つ。

名義尺度は「ラベル間に順序も等間隔性もない」 データ型。 SSDSE-B-2026 の「都道府県名」(北海道、 青森…)、 「地方区分」(北海道地方、 東北地方…) は典型的な名義尺度。 平均や標準偏差は意味を持たず、 利用できる統計は「頻度」「最頻値」「χ² 検定」「カイ二乗独立性検定」など限定される。

本ページでは (1) 入力: 47 都道府県名と地方区分 → (2) 処理: 頻度集計と one-hot エンコーディング → (3) 出力: クロス集計表と最頻値 → (4) 解釈: 「同じ地方の県は人口規模の分布が似るか」を χ² で検定、 の 4 段階で扱う。

次節以降では、 SSDSE-B-2026 の 47 県を 8 地方区分でクロス集計し、 χ² 統計量を手計算 (期待度数の式から) で求め、 scipy.stats.chi2_contingency で再現する流れを示す。

📐 定義・数式

🍰 まずはやさしく

名義尺度は、4つの尺度の中で最も単純なものです。

データの性質を正しく定義するために使います。

都道府県と年代の組み合わせなどで考えます。

数式を使った関連度の測り方について読みます。

【Stevens の尺度水準】
$$ \text{Nominal} \subset \text{Ordinal} \subset \text{Interval} \subset \text{Ratio} $$

Stevens (1946) の 4 段階分類。 名義は最も情報量が少なく、 比例尺度が最大。 名義データに対しては集合演算と頻度しか定義できない。

📐 数理的導出:Cramér V とカイ二乗の関係

2 つの名義変数の関連度を測る代表的指標 Cramér V は、 カイ二乗統計量 $\chi^2$ を標本サイズ $n$ と (行数 $r$, 列数 $c$) の小さい方 $-1$ で正規化した量です:

$$ V = \sqrt{\dfrac{\chi^2}{n \cdot \min(r-1, c-1)}} $$

$V \in [0, 1]$ で、 0 が独立、 1 が完全関連。 SSDSE-B-2026 で「都道府県」(47 カテゴリ) と「年代区分」(5 カテゴリ) の関連を見るなら、 $\min(r-1, c-1) = 4$ として正規化。 標本サイズに依存しない比較が可能です。

$\chi^2$ 自体は $\chi^2 = \sum_{i,j} \dfrac{(O_{ij} - E_{ij})^2}{E_{ij}}$。 ここで $O_{ij}$ は観測度数、 $E_{ij} = \dfrac{R_i \cdot C_j}{n}$ は独立性仮説下の期待度数。 期待度数が小さい (< 5) セルが多いと近似が悪化し、 Fisher の正確検定や Monte Carlo シミュレーションが必要です。

類似指標との比較

指標値域主な用途対称性
Phi coefficient[-1, 1]2x2 表のみ対称
Cramér V[0, 1]r×c 表全般対称
Goodman-Kruskal λ[0, 1]予測 A→B 改善度非対称
Theil U[0, 1]情報量ベース非対称
Uncertainty coefficient[0, 1]エントロピーベース非対称

📜 歴史事例:名義データの解釈にまつわる教訓

事例 1:Snow のコレラ地図 (1854)

ロンドンの医師 John Snow がコレラ発生地点を地図にプロット ── 「Broad Street の井戸」という名義カテゴリが原因と特定。 名義データを地理的に可視化することで因果が見えた歴史的事例。 現代でも地名・施設名のジオコーディングは強力な分析ツールです。

事例 2:花粉症都道府県別罹患率 (現代)

「都道府県」(名義) と「花粉症罹患率」(比例) の関連を見ると、 杉花粉飛散量とよく相関。 ただし「沖縄=杉樹少なし=低罹患」のように、 単純な平均比較が誤導することはなく、 名義カテゴリは地理的・気候的特性の総合代理として機能。

事例 3:血液型と性格 (擬似科学)

日本で人気の「血液型性格分類」は名義 (血液型 A/B/O/AB) と順序/間隔 (性格特性) の相関を主張。 大規模調査 (n>10,000) で有意な関連なしと確認済み。 名義変数を使うと「グループ間で何か違う」と感じやすい認知バイアスの典型例。

事例 4:選挙投票行動の名義変数化

「政党名」は名義変数ですが、 「保守 ← → リベラル」軸に再コーディングすると順序尺度として扱える。 米国 NES (National Election Studies) では伝統的にこの変換を採用。 ただし元データの情報は失われるため、 タスクに応じて使い分け。

事例 5:医療診断コード ICD-10

国際疾病分類 ICD-10 は約 14,000 のカテゴリを持つ巨大な名義変数。 そのまま One-Hot 化は次元爆発。 階層的に「章 → ブロック → カテゴリ」と集約するか、 医学的近似度を学習した Embedding が現実的解。

🎯 分野別応用:名義尺度をどう扱うか

① マーケティング

顧客セグメント (例:「都道府県」「業界」「会社規模カテゴリ」) は名義データの宝庫。 RFM 分析、 ペルソナ設計、 ターゲティング広告の入力として頻出。 Target Encoding で「CVR (コンバージョン率)」に変換する手法が定番。

② 公衆衛生

疾患カテゴリ (ICD-10)、 死因区分、 検査結果区分 (陰性/陽性/判定保留) すべて名義。 疫学研究では「曝露 × 結果」の 2x2 表からオッズ比・相対リスクを計算 ── これは名義 × 名義の基本分析パターンです。

③ 自然言語処理

単語・トークン (語彙) は超高次元名義変数 (語彙サイズ 30,000〜100,000)。 One-Hot は非効率なので、 Word Embedding (word2vec, BERT) で連続ベクトル空間に写像。 これは「名義 → 連続」変換の代表例で、 ML の基礎技術となっています。

④ レコメンダーシステム

ユーザー ID・商品 ID (名義) を Embedding 学習することで、 協調フィルタリングが実現。 Matrix Factorization は本質的に「2 つの名義変数を低次元連続空間に写像する」操作です。

⑤ バイオインフォマティクス

遺伝子変異 (SNP) は 3 カテゴリ名義 (AA/AG/GG)。 ゲノムワイド関連解析 (GWAS) では数百万 SNP を独立にカイ二乗検定。 多重検定補正 (Bonferroni) が必須。

📐 名義変数の「散らばり」を測る: Shannon Entropy と Gini Index

名義変数には標準偏差が無いため、 「散らばり」は別の尺度が必要。 代表が Shannon EntropyGini Index

$$H(X) = -\sum_{i=1}^{k} p_i \log_2 p_i \quad \text{(ビット)}$$

$$G(X) = 1 - \sum_{i=1}^{k} p_i^2 \quad \text{(0-1)}$$

🔬 数式を言葉で読み解く

🎯 このコードでやること: 47 県の Region (8 地方) の散らばりを Shannon Entropy と Gini Index で測る。 また、 「進学率」によって分割した際の Region の Information Gain を計算する。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 E4601(高等学校卒業者数) E4602(高等学校卒業者のうち進学者数) 北海道 34,467 18,177 東京都 93,495 69,302 沖縄県 13,022 6,080 …(全 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
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()
region_map = {
    '北海道':'北海道',
    '青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北',
    '茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東',
    '新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部',
    '三重県':'近畿','滋賀県':'近畿','京都府':'近畿','大阪府':'近畿','兵庫県':'近畿','奈良県':'近畿','和歌山県':'近畿',
    '鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国',
    '徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国',
    '福岡県':'九州','佐賀県':'九州','長崎県':'九州','熊本県':'九州','大分県':'九州','宮崎県':'九州','鹿児島県':'九州','沖縄県':'九州',
}
d['Region'] = d['Prefecture'].map(region_map)

def shannon(p):
    p = p[p > 0]
    return -np.sum(p * np.log2(p))

def gini(p):
    return 1 - np.sum(p ** 2)

p_region = d['Region'].value_counts(normalize=True).values
H = shannon(p_region)
G = gini(p_region)
print(f'Region (8 カテゴリ) Shannon Entropy: {H:.3f} bits (max={np.log2(8):.3f})')
print(f'Region (8 カテゴリ) Gini Index: {G:.3f} (max={1 - 1/8:.3f})')

# 進学率 ≥ 0.6 で分割した条件付きエントロピー
d['GoHigh'] = (d['E4602'] / d['E4601'] >= 0.6).astype(int)
H_cond = 0
for v in [0, 1]:
    sub = d[d['GoHigh'] == v]
    if len(sub) == 0:
        continue
    p_sub = sub['Region'].value_counts(normalize=True).values
    H_v = shannon(p_sub)
    w = len(sub) / len(d)
    H_cond += w * H_v
    print(f'  GoHigh={v}: N={len(sub)}, H(Region|GoHigh={v})={H_v:.3f}')
print(f'\nH(Region|GoHigh) = {H_cond:.3f}')
print(f'Information Gain: {H - H_cond:.3f}')

📤 実行結果:

Region (8 カテゴリ) Shannon Entropy: 2.853 bits (max=3.000) Region (8 カテゴリ) Gini Index: 0.855 (max=0.875) GoHigh=0: N=32, H(Region|GoHigh=0)=2.804 GoHigh=1: N=15, H(Region|GoHigh=1)=1.826 H(Region|GoHigh) = 2.492 Information Gain: 0.362

💬 結果の読み方: Region の Shannon Entropy 2.853 bits は最大 3.000 bits に近く、 8 地方は かなり均等に分布。 進学率 ≥ 0.6 で分割したときの Information Gain は 0.362 bits(H の約 13%)— 「進学率が高いかどうか」からは「どの地方か」を部分的にしか予測できない。 これは決定木の split criterion と同じ原理で、 名義変数の予測可能性を測る。

📐 名義尺度の Cramer's V 計算 (関連の強さの数値化)

このコードでやること: 2 つの名義変数(地方区分 × 人口規模区分)の関連の強さを Cramer's V (0-1) で計測する。 Pearson r が使えない名義変数同士でも、 0 = 独立、 1 = 完全関連 の正規化された指標が得られる。 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
import pandas as pd, numpy as np
from scipy.stats import chi2_contingency

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].copy()

def to_region(p):
    east = ['青森県','岩手県','宮城県','秋田県','山形県','福島県','茨城県','栃木県','群馬県',
            '埼玉県','千葉県','東京都','神奈川県','新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県']
    if p == '北海道': return '北海道'
    if p == '沖縄県': return '沖縄'
    return '東日本' if p in east else '西日本'

df['地方'] = df['Prefecture'].map(to_region)
df['人口規模'] = pd.cut(df['A1101'], bins=[0, 1_000_000, 3_000_000, 20_000_000],
                      labels=['小','中','大'])

ct = pd.crosstab(df['地方'], df['人口規模'])
chi2, p, dof, _ = chi2_contingency(ct)
n = ct.values.sum()
cramers_v = np.sqrt(chi2 / (n * (min(ct.shape) - 1)))
print(ct)
print(f'\nχ² = {chi2:.3f}, p = {p:.4f}')
print(f"Cramer's V = {cramers_v:.3f}")
print('→ 0.1=弱, 0.3=中, 0.5=強の関連')

📤 実行例:

人口規模 小 中 大 地方 北海道 0 0 1 東日本 3 13 6 沖縄 0 1 0 西日本 7 13 3 χ² = 7.069, p = 0.3145 Cramer's V = 0.274 → 0.1=弱, 0.3=中, 0.5=強の関連

💬 結果の読み方: Cramer's V = 0.274 は「弱〜中程度の関連」。 χ² 検定の p = 0.31 で有意差なし、 関連の絶対値も小さい。 つまり 地方と人口規模は強く独立ではないが、 統計的な関連は弱い。 Cramer's V は Pearson r と違って 0-1 の片側スケール (符号なし) で、 高基数の名義変数同士でも比較可能な唯一の選択肢。 名義 × 名義の関連を「相関ヒートマップ」風に見たいときは、 全 2 変数ペアで Cramer's V を計算してヒートマップ化する。

📊 名義 × 名義 関連指標の使い分け

指標範囲特性SSDSE-B-2026 での適用例
Cramer's V0 〜 1対称、 N に依存しない地方 × 人口規模 (上の例)
φ 係数-1 〜 12×2 表のみ、 符号あり都市/地方 × 高/低人口
Theil's U0 〜 1非対称、 情報量基準「地方 → 産業」の予測力
Mutual Information0 〜 ∞対称、 非線形関係も検出機械学習の特徴量選択

🔬 数式を言葉で読み解く

数式に出てくる記号の意味を 1 つずつ確認しましょう。

Nominal
順序なし。 性別・血液型。
Ordinal
順序あり、 間隔不明。 満足度 1〜5。
Interval
間隔あり、 絶対 0 なし。 温度 °C。
Ratio
絶対 0 あり。 質量・人数。

🔬 数式を言葉で読み解く(500字+ narration)

Stevens (1946) は心理測定の文脈で 「測定 (measurement)」とは何かを問い、 値の集合に対して許容される変換群 (admissible transformations) の広さによって尺度を 4 段階に整理しました。 名義尺度の場合、 許容される変換は 1 対 1 の全単射 (bijection) です。 つまり「A → 1、 B → 2、 O → 3、 AB → 4」と数値を割り当てても、 「A → 99、 B → 17、 O → 5、 AB → 42」と入れ替えても、 含まれる情報量は同じです。 数値の差や比は元データの構造を反映していません。 そのため、 平均 $\bar{x}$ や標準偏差 $s$ といった順序や距離を前提とする統計量は意味を持たず、 頻度 $f_k = \#\{i: x_i = c_k\}$最頻値 $\arg\max_k f_k$、 そして相対頻度 $p_k = f_k / n$ しか不変的に解釈できません。 SSDSE-B-2026 でいえば「都道府県名」「地域コード」「気候区分」は名義です。 これらに対して「平均都道府県」を計算しても、 それはコードの恣意的な割り当てに依存する数字でしかなく、 解釈不能。 一方で「都道府県別の人口の平均」は意味があります ── 平均する対象が人口 (比例尺度) だからです。 この区別が現代の前処理パイプラインの設計、 特に OneHotEncoderOrdinalEncoder の使い分けに直結しており、 後者を名義データに使うと木モデル以外では誤った仮定が混入します。 結局、 数式 $\text{Nominal} \subset \text{Ordinal} \subset \text{Interval} \subset \text{Ratio}$ は「情報の包含関係」を表し、 包含関係の下位に位置する名義は、 上位の尺度を前提とした演算 (平均・分散・相関) を持ち込めない、 という制約宣言でもあるのです。

📖 4 要素 narration — 名義尺度を 4 つの視点で再読する

① 直感の narration

「血液型 A・B・O・AB」を例にしましょう。 もし誰かが「血液型の平均は B.5 です」と言ったらどう感じますか? 違和感を覚えるはずです。 これが名義尺度の本質です ── 値はラベルであってではない。 都道府県、 性別、 メーカー名、 駅名、 病名 ── これらすべてが名義です。 平均は計算可能 (数値化すれば) ですが、 解釈に意味がありません。

② 数式の narration

記号 $\text{Nominal} \subset \text{Ordinal}$ は「名義は順序に含まれる」と読みます。 これは Stevens の階層を表し、 名義は最も情報量が少ない (もっとも制約が少ない/許容される変換が広い) 尺度。 「$\subset$」は「許容される統計操作の集合」が含まれるという意味で、 逆方向には包含しません。 つまり順序尺度では中央値が定義できるが名義尺度では定義できない、 という非対称性を意識してください。

③ 計算の narration

SSDSE-B-2026 で「都道府県」列を value_counts() すると 47 行が均一に 12 ずつ出ます。 これは年×県の完全直積データだからです。 もしここで「平均都道府県コード」を計算しても、 コードの順序自体が任意なので意味はありません。 同じ手続きを「総人口(A1101)」(比例尺度) に適用すれば、 平均人口というれっきとした統計量が得られます ── 尺度判定が分析の入り口です。

④ Python の narration

pd.get_dummies(df, columns=['都道府県']) は 1 列を 47 列の 0/1 ダミーに展開します。 これが One-Hot Encoding の最小実装。 一方、 scikit-learn の OneHotEncoder(handle_unknown='ignore') を Pipeline に組み込めば、 訓練・推論で同じ列構造を維持できます。 木モデル (LightGBM/CatBoost) では categorical_feature 引数で名義列を指定すれば、 内部で最適分割を学習します ── One-Hot 化は不要です。

🔬 Stevens 4 尺度水準の全体像 — 名義尺度の位置づけ

Stevens (1946) は「測定」を 4 段階に分類した。 上位ほど演算が許される。

水準許容演算代表統計量
名義 (Nominal)=, ≠最頻値, 度数都道府県, 血液型, 性別
順序 (Ordinal)=, ≠, <, >中央値, 四分位学年, 満足度 (1-5)
間隔 (Interval)+, -算術平均, 標準偏差気温 (摂氏), 年号
比 (Ratio)+, -, ×, ÷幾何平均, 変動係数人口, 距離, 重さ

💬 SSDSE-B-2026 を例にすると: 名義=都道府県・地域コード、 順序=学校種別の進学段階、 間隔=年平均気温 (℃)、 =総人口・出生数・大学数。 「名義変数を比 (人口) と組み合わせる」のがクロス集計、 「名義 × 比」の標準的解析法。

🧮 実値で計算してみる

都道府県名は名義尺度。 頻度集計・最頻値・棒グラフが正しい扱い。

STEP 1 尺度判定
値に順序があるか確認。
STEP 2 頻度集計
value_counts で各カテゴリの個数を算出。
STEP 3 可視化
棒グラフ・円グラフ。
STEP 4 ML で使う場合
One-Hot か Target Encoding。

🧮 SSDSE-B-2026 で実際に集計

独立行政法人統計センターが提供する SSDSE-B-2026(都道府県・時系列データ)を用いて、 名義尺度列の正しい扱いを実演します。 このデータには「都道府県(Prefecture)」列が含まれ、 47 都道府県 × 12 年分(2012–2023)で 564 行あります。 「都道府県」は名義、 「年(SSDSE-B-2026 列)」は順序、 「総人口(A1101)」は比例 ── と尺度を見極めることが第一歩です。

📥 入力例(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
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 1. 列の尺度を判定する補助関数
def scale_of(s):
    if s.dtype == 'object': return 'nominal/ordinal?'
    return 'interval/ratio'
for col in df.columns[:6]:
    print(col, scale_of(df[col]))
# 2. 名義尺度らしい列(Prefecture)の頻度集計
print(df['Prefecture'].value_counts().head())
# 3. 平均はナンセンス。最頻値を取る
print('mode:', df['Prefecture'].mode().iloc[0])
📤 実行例(実測) SSDSE-B-2026 interval/ratio Code nominal/ordinal? Prefecture nominal/ordinal? A1101 interval/ratio A110101 interval/ratio A110102 interval/ratio Prefecture 北海道 12 徳島県 12 大阪府 12 兵庫県 12 奈良県 12 Name: count, dtype: int64 mode: 三重県

結果として 47 県すべて 12 回ずつ出現するため value_counts は均一になります。 これは「データ収集設計上の意味」を示します ── 名義データの偏りはサンプリングの偏りを示唆する重要なシグナルです。

1
2
3
4
5
6
# 4. ある説明変数(総人口 A1101)を Prefecture でグループ化し平均を取る
agg = df.groupby('Prefecture')['A1101'].mean().sort_values(ascending=False)
print(agg.head(10))
# 5. One-Hot Encoding で機械学習に渡す
X = pd.get_dummies(df[['Prefecture']], prefix='pref')
print('encoded shape:', X.shape, '-> 47 列に展開')
📤 実行例(実測) Prefecture 東京都 1.374541e+07 神奈川県 9.171963e+06 大阪府 8.829346e+06 愛知県 7.499462e+06 埼玉県 7.297692e+06 千葉県 6.247596e+06 兵庫県 5.493650e+06 北海道 5.297196e+06 福岡県 5.113731e+06 静岡県 3.662792e+06 Name: A1101, dtype: float64 encoded shape: (564, 47) -> 47 列に展開

🧮 SSDSE-B-2026 の 47 都道府県を「名義尺度」として徹底分析

「都道府県」はカテゴリ間に 順序が無い典型的な名義尺度です (北海道 < 青森県 とは言えない)。 一方、 8 地方区分 (北海道/東北/関東/中部/近畿/中国/四国/九州) も 同じく名義尺度です。 ここでは SSDSE-B-2026 で 47 県を地方ブロックに対応させ、 名義変数として扱える操作 (集計・最頻値・カイ二乗検定・Cramér's V) を実演します。

📐 名義尺度の演算可能性 (Stevens 1946)

Stevens の 4 尺度水準 (Nominal / Ordinal / Interval / Ratio) では、 名義尺度は最下層。 許される演算は:

🔬 数式を言葉で読み解く: Cramér's V

$$V = \sqrt{\frac{\chi^2}{N \cdot (\min(r,c) - 1)}}$$

🐍 47 県 × 8 地方 × 人口階級のクロス集計とカイ二乗検定

🎯 このコードでやること: SSDSE-B-2026 で 47 県を 8 地方ブロック (名義) に分類し、 さらに人口階級 (小=100 万未満・中=100-300 万・大=300 万以上) と組み合わせて χ² 検定 + Cramér's V を計算。

📥 入力: 47 県の Prefecture (名義), A1101 (総人口・連続)

 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
import pandas as pd
import numpy as np
from scipy.stats import chi2_contingency

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

# 8 地方ブロック (名義尺度) への対応
region_map = {
    '北海道':'北海道',
    '青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北',
    '茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東',
    '新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部',
    '三重県':'近畿','滋賀県':'近畿','京都府':'近畿','大阪府':'近畿','兵庫県':'近畿','奈良県':'近畿','和歌山県':'近畿',
    '鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国',
    '徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国',
    '福岡県':'九州','佐賀県':'九州','長崎県':'九州','熊本県':'九州','大分県':'九州','宮崎県':'九州','鹿児島県':'九州','沖縄県':'九州',
}
d['Region'] = d['Prefecture'].map(region_map)
d['PopClass'] = pd.cut(d['A1101'], bins=[0, 1_000_000, 3_000_000, 20_000_000],
                       labels=['小', '中', '大'])

tab = pd.crosstab(d['Region'], d['PopClass'])
chi2, p, dof, exp = chi2_contingency(tab)
N = tab.sum().sum()
V = np.sqrt(chi2 / (N * (min(tab.shape) - 1)))

print(tab)
print(f'\nchi2 = {chi2:.3f}, p = {p:.4f}, dof = {dof}')
print(f"Cramér's V = {V:.3f}")

📤 実行結果:

PopClass 小 中 大 Region 中国 2 3 0 中部 2 5 2 九州 1 6 1 北海道 0 0 1 四国 3 1 0 東北 1 5 0 近畿 1 4 2 関東 0 3 4 chi2 = 21.978, p = 0.0791, dof = 14 Cramér's V = 0.484

💬 結果の読み方: p=0.079 で 5% 有意水準では帰無仮説 (Region と PopClass が独立) は棄却されない。 ただし Cramér's V = 0.484 と中程度以上の関連が示唆される。 関東は「大」3 件・「中」3 件で大規模県集中、 四国は「小」3 件で小規模偏向。 N=47 と小標本のため χ² の検出力が弱いだけで、 実質的な関連は強い。 これは「名義変数間の関連を、 サンプル小では p 値だけでは判断できない」典型例。

🧮 47 都道府県 → 8 地方ブロック集約: 名義変数 groupby

名義変数の典型操作は groupby + 集計。 47 県を 8 地方に集約すると、 SSDSE-B-2026 の主要指標が見える。

🎯 このコードでやること: 8 地方ブロックで人口・大学数・大学生数・進学率を集計し、 ブロック間格差を確認する。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) E4601(高等学校卒業者数) E4602(高等学校卒業者のうち進学者数) E6102(大学数) E6302(大学学生数) 北海道 5,092,000 34,467 18,177 37 79,983 東京都 14,086,000 93,495 69,302 144 681,667 沖縄県 1,468,000 13,022 6,080 8 17,937 …(全 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
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()
region_map = {
    '北海道':'北海道',
    '青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北',
    '茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東',
    '新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部',
    '三重県':'近畿','滋賀県':'近畿','京都府':'近畿','大阪府':'近畿','兵庫県':'近畿','奈良県':'近畿','和歌山県':'近畿',
    '鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国',
    '徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国',
    '福岡県':'九州','佐賀県':'九州','長崎県':'九州','熊本県':'九州','大分県':'九州','宮崎県':'九州','鹿児島県':'九州','沖縄県':'九州',
}
d['Region'] = d['Prefecture'].map(region_map)

agg = d.groupby('Region').agg(
    Pop=('A1101', 'sum'),
    Univ=('E6102', 'sum'),
    Students=('E6302', 'sum'),
    HSGrad=('E4601', 'sum'),
    UnivGo=('E4602', 'sum'),
    N=('Prefecture', 'count')
)
agg['UnivPer1M'] = agg['Univ'] / agg['Pop'] * 1_000_000
agg['GoRate'] = agg['UnivGo'] / agg['HSGrad']
print(agg.round(2).to_string())

📤 実行結果:

Pop Univ Students HSGrad UnivGo N UnivPer1M GoRate Region 中国 7070000 54 124519 54915 31693 5 7.64 0.58 中部 20749000 144 340663 162801 98204 9 6.94 0.60 九州 14029000 80 215296 112484 58812 8 5.70 0.52 北海道 5092000 37 79983 34467 18177 1 7.27 0.53 四国 3578000 18 46806 27238 15871 4 5.03 0.58 東北 8318000 52 109658 63499 33231 6 6.25 0.52 近畿 21990000 158 567350 164196 110224 7 7.19 0.67 関東 43527000 267 1148500 299250 201912 7 6.13 0.67

💬 結果の読み方: 関東は最大の人口 (43,527,000) と最多の大学数 (267) を持つが、 100万人あたり大学数は 6.13 と中位にとどまり、 密度首位は中国 7.64、 最下位は四国 5.03。 進学率は関東・近畿の 67% が高く、 東北 52% / 九州 52% / 北海道 53% が低い。 これらは「名義変数 (地方ブロック) × 量的変数 (率・密度)」の交差表で初めて見えるパターン。 単に「東京は大学が多い」と一言で済まされない構造があります。

🧮 数式に値を入れて手で計算する: 名義尺度のカイ二乗

合成 3 カテゴリで一様分布との適合度を χ² で検定する。

Step 1: 観測度数

カテゴリ観測 O期待 E (一様)
A5030
B2530
C1530

合計 90, 期待 90/3=30

Step 2: χ²

χ² = Σ(O-E)²/E = 400/30 + 25/30 + 225/30 = 13.33 + 0.83 + 7.50 = 21.67 df=2, χ²(0.05, 2)=5.99 → 一様棄却

🐍 Python で再現

1
2
3
4
5
6
from scipy import stats
O = [50, 25, 15]
E = [30, 30, 30]
chi2, p = stats.chisquare(O, E)
print(f"χ² = {chi2:.2f}")
print(f"p = {p:.4f}")

📤 実行結果

χ² = 21.67 p = 0.0000

💬 手計算 (Step 2) 21.67 と Python 出力が完全一致。

🐍 Python 実装

最小実装の例。 SSDSE のような実データに対して、 まずはコピペで動かしてみるのが理解の早道です。

📥 入力例(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
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 都道府県(Prefecture)は名義尺度
print(df['Prefecture'].value_counts())
# ML 用:One-Hot Encoding
X = pd.get_dummies(df, columns=['Prefecture'])
📤 実行例(実測) Prefecture 北海道 12 徳島県 12 大阪府 12 兵庫県 12 奈良県 12 和歌山県 12 鳥取県 12 島根県 12 岡山県 12 広島県 12 山口県 12 香川県 12 滋賀県 12 愛媛県 12 高知県 12 福岡県 12 佐賀県 12 長崎県 12 熊本県 12 …

🐍 名義変数の符号化 (Encoding) — 4 手法の比較

機械学習では「名義変数 → 数値」変換が必須。 手法によって性能と落とし穴が大きく違うので、 SSDSE-B-2026 の 47 県を題材に One-hot / Label / Target / Frequency の 4 方式を比較します。

🎯 このコードでやること: 47 都道府県を 4 方式で符号化し、 出力次元・情報量を比較する。

📥 入力: 47 県 Prefecture (名義) と総人口 A1101 (target に使用)

 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
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, LabelEncoder

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

# 1. One-hot Encoding (47 列, 大半が 0)
ohe = OneHotEncoder(sparse_output=False).fit(d[['Prefecture']])
X_ohe = ohe.transform(d[['Prefecture']])
print(f'1. One-hot: shape={X_ohe.shape}, 非ゼロ要素数/全要素={int(X_ohe.sum())}/{X_ohe.size}')

# 2. Label Encoding (1 列, 整数 0-46)
le = LabelEncoder()
X_label = le.fit_transform(d['Prefecture'])
print(f'2. Label: shape={X_label.shape}, 範囲={X_label.min()}-{X_label.max()}')
print(f'   注意: 北海道=1, 沖縄=46 のような順序が「人為的」に生じる')

# 3. Target Encoding (1 列, 対象変数の平均値で置換)
target = d['A1101']
d['Pref_target'] = d.groupby('Prefecture')['A1101'].transform('mean')
print(f'3. Target: shape=(47,), 例: 東京都={d.loc[d["Prefecture"]=="東京都","Pref_target"].iloc[0]}')

# 4. Frequency Encoding (1 列, 出現頻度で置換)
freq = d['Prefecture'].value_counts(normalize=True)
d['Pref_freq'] = d['Prefecture'].map(freq)
print(f'4. Frequency: 各県 1/47 ≈ {1/47:.4f} (1 年データなら全県同じ)')

📤 実行結果:

1. One-hot: shape=(47, 47), 非ゼロ要素数/全要素=47/2209 2. Label: shape=(47,), 範囲=0-46 注意: 北海道=1, 沖縄=46 のような順序が「人為的」に生じる 3. Target: shape=(47,), 例: 東京都=14086000 4. Frequency: 各県 1/47 ≈ 0.0213 (1 年データなら全県同じ)

💬 結果の読み方: ① One-hot は 47 列に展開 (高次元・スパース・解釈容易) ② Label は 1 列で済むが 順序がない名義変数に順序を強制するため、 線形モデル・距離ベース手法では NG。 決定木では使用可。 ③ Target は予測対象を直接埋め込むため強力だが データリーケージに注意 (cross-validation 必須)。 ④ Frequency は出現頻度ベースで、 多年データなら有効。 SSDSE-B-2026 のように 1 年 = 47 行なら無意味。

🐍 pandas.Categorical: 名義 vs 順序を明示する

pandas の Categorical 型は ordered 引数で名義/順序を切り替えられる。 これを使うと、 順序付き Categorical なら < 比較が可能、 名義なら不可になる。

🎯 このコードでやること: 47 県を「ordered=False (名義)」「ordered=True (順序)」で作り、 比較演算の振る舞いを確認する。

📥 入力: 47 県の Prefecture 列

 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
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

# 名義 (ordered=False, デフォルト)
d['Pref_nom'] = pd.Categorical(d['Prefecture'], ordered=False)
print(f'名義 Categorical: {d["Pref_nom"].dtype}')
print(f'  メモリ: {d["Pref_nom"].memory_usage()} bytes (vs object {d["Prefecture"].memory_usage()})')

# 順序 (ordered=True, 例: 北から南へ並べる)
order = ['北海道','青森県','岩手県','宮城県','秋田県','山形県','福島県',
         '茨城県','栃木県','群馬県','埼玉県','千葉県','東京都','神奈川県',
         '新潟県','富山県','石川県','福井県','山梨県','長野県','岐阜県','静岡県','愛知県',
         '三重県','滋賀県','京都府','大阪府','兵庫県','奈良県','和歌山県',
         '鳥取県','島根県','岡山県','広島県','山口県',
         '徳島県','香川県','愛媛県','高知県',
         '福岡県','佐賀県','長崎県','熊本県','大分県','宮崎県','鹿児島県','沖縄県']
d['Pref_ord'] = pd.Categorical(d['Prefecture'], categories=order, ordered=True)

# 比較演算
print(f"\n順序 Categorical で東京 > 北海道 ? {d['Pref_ord'][d['Prefecture']=='東京都'].iloc[0] > d['Pref_ord'][d['Prefecture']=='北海道'].iloc[0]}")

# 名義ではエラー
try:
    d['Pref_nom'][d['Prefecture']=='東京都'].iloc[0] > d['Pref_nom'][d['Prefecture']=='北海道'].iloc[0]
except TypeError as e:
    print(f"名義 Categorical で比較 → TypeError: {str(e)[:50]}")

📤 実行結果:

名義 Categorical: category メモリ: 1871 bytes (vs object 752) 順序 Categorical で東京 > 北海道 ? True 名義 Categorical で比較 → TypeError: Unordered Categoricals can only compare equ

💬 結果の読み方: メモリは 2023 年の 47 行 (47 県がすべてユニーク) ではカテゴリ辞書の分だけ逆に増える (752→1871 bytes)。 Categorical のメモリ削減効果が出るのは同じ値が繰り返す場合で、 全 564 行 (47 県 × 12 年) なら 4644→2012 bytes と半分以下になる。 順序 Categorical は > が使えるが、 名義は TypeError。 これは Stevens の尺度水準を 型レベルで強制する仕組み。 sklearn の OrdinalEncoder は順序を強制するため、 名義変数に使うと暗黙の順序仮定が入ってしまう。

🐍 多項ロジスティック回帰: 名義尺度がターゲットの場合

名義変数がターゲット (Y) であれば、 多項ロジスティック回帰 (Multinomial Logistic Regression) を使う。 SSDSE-B-2026 で「ある県がどの地方ブロックに属するか」を、 数値特徴量から予測してみる。

🎯 このコードでやること: 47 県の {人口・気温・大学数} から「8 地方ブロックの予測」を多項ロジ回帰で学習し、 混同行列を出す。

📥 入力: 特徴量 X = [A1101, B4101, E6102] (人口, 平均気温, 大学数)、 ターゲット = 地方ブロック (8 名義値)

 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
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import confusion_matrix, classification_report

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

region_map = {
    '北海道':'北海道',
    '青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北',
    '茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東',
    '新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部',
    '三重県':'近畿','滋賀県':'近畿','京都府':'近畿','大阪府':'近畿','兵庫県':'近畿','奈良県':'近畿','和歌山県':'近畿',
    '鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国',
    '徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国',
    '福岡県':'九州','佐賀県':'九州','長崎県':'九州','熊本県':'九州','大分県':'九州','宮崎県':'九州','鹿児島県':'九州','沖縄県':'九州',
}
d['Region'] = d['Prefecture'].map(region_map)

X = StandardScaler().fit_transform(d[['A1101', 'B4101', 'E6102']].values)
y = d['Region'].values

clf = LogisticRegression(max_iter=1000).fit(X, y)
pred = clf.predict(X)
print(f'訓練精度: {(pred == y).mean():.3f}')
print(f'\n各県の予測:')
for pref, true_r, pred_r in zip(d['Prefecture'], y, pred):
    if true_r != pred_r:
        print(f'  {pref}: 真={true_r} → 予測={pred_r}')

📤 実行結果 (例):

訓練精度: 0.468 各県の予測: 北海道: 真=北海道 → 予測=東北 宮城県: 真=東北 → 予測=中部 福島県: 真=東北 → 予測=中部 茨城県: 真=関東 → 予測=中部 栃木県: 真=関東 → 予測=中部 ...

💬 結果の読み方: 訓練精度 46.8% — 8 クラス分類で random ベース 12.5% よりは高いが、 「人口・気温・大学数」だけでは地方ブロックを再現できない。 地方ブロックは「地理 + 文化 + 歴史」の混合であり、 単純な数値特徴では不十分。 多項ロジ回帰のソフトマックス出力 (clf.predict_proba) を見ると、 上位 2 ブロックが拮抗していることが多い。 名義ターゲットでは精度 (accuracy) より各クラスの recall/precision を見る方が良い。

🐍 連想規則: 名義変数間のパターン抽出

名義変数の組合せを「もし A なら B」のルールに展開するのが連想規則 (Association Rule)。 ここでは 47 都道府県の 4 つの属性 ({高人口/低人口} × {高大学/低大学} × {太平洋側/日本海側} × {大都市/地方}) からルールを抽出する。

🎯 このコードでやること: 47 県を 4 つの 2 値属性で記述し、 mlxtend で頻出アイテム集合と連想規則を抽出。

📥 入力: 47 県 × 4 属性 (二値化)

 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
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

# 4 つの 2 値属性 (すべて名義)
big_list = ['東京都','神奈川県','埼玉県','千葉県','大阪府','愛知県']
pacific = ['東京都','神奈川県','千葉県','茨城県','静岡県','愛知県','三重県','和歌山県',
           '徳島県','高知県','宮崎県','岩手県','宮城県','福島県']

d['HighPop'] = (d['A1101'] >= 2_500_000).astype(int)
d['HighUniv'] = (d['E6102'] >= 15).astype(int)
d['Pacific'] = d['Prefecture'].isin(pacific).astype(int)
d['Big'] = d['Prefecture'].isin(big_list).astype(int)

print(d[['Prefecture','HighPop','HighUniv','Pacific','Big']].head(10).to_string(index=False))
# 簡易連想規則: 大都市 → 高人口
rule_big2highpop = ((d['Big']==1) & (d['HighPop']==1)).sum() / (d['Big']==1).sum()
rule_highpop2highuniv = ((d['HighPop']==1) & (d['HighUniv']==1)).sum() / (d['HighPop']==1).sum()
print(f'\n[大都市 → 高人口] confidence: {rule_big2highpop:.3f}')
print(f'[高人口 → 高大学] confidence: {rule_highpop2highuniv:.3f}')

# Lift = P(B|A) / P(B)
lift = rule_highpop2highuniv / (d['HighUniv']==1).mean()
print(f'[高人口 → 高大学] lift: {lift:.3f} (1 より大きいなら関連あり)')

📤 実行結果 (例):

Prefecture HighPop HighUniv Pacific Big 北海道 1 1 0 0 青森県 0 0 0 0 岩手県 0 0 1 0 宮城県 0 0 1 0 秋田県 0 0 0 0 山形県 0 0 0 0 福島県 0 0 1 0 茨城県 1 0 1 0 栃木県 0 0 0 0 群馬県 0 1 0 0 [大都市 → 高人口] confidence: 1.000 [高人口 → 高大学] confidence: 0.846 [高人口 → 高大学] lift: 2.841

💬 結果の読み方: ① 大都市 6 県 → 全員が高人口 (confidence=1.0)。 ② 高人口 13 県のうち 11 県が高大学 (confidence=0.846)。 lift=2.841 は「高人口だと高大学である確率が、 ランダムより 2.84 倍高い」を意味する。 これは名義変数間の関連を「規則」として明示的に表現する手法で、 マーケットバスケット解析 (Apriori) の応用。

🐍 練習問題: 47 県の「ホテル偏在度」を名義変数として可視化

🎯 このコードでやること: SSDSE-B-2026 の旅館営業施設数(ホテルを含む) (C3801) と、 県名 (名義) を組み合わせ、 ホテル集中度の上位 / 下位を可視化する。

📥 入力: 47 県 Prefecture + C3801 (旅館営業施設数)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
d = df[df['SSDSE-B-2026'] == 2023].copy()

# ホテル数を県別に集計、 100万人あたりに換算
d['HotelPer1M'] = d['C3801'] / d['A1101'] * 1_000_000
sorted_d = d.sort_values('HotelPer1M', ascending=False)
print('ホテル密度 上位 5 県 (100万人あたり):')
print(sorted_d[['Prefecture','C3801','A1101','HotelPer1M']].head(5).to_string(index=False))
print('\nホテル密度 下位 5 県:')
print(sorted_d[['Prefecture','C3801','A1101','HotelPer1M']].tail(5).to_string(index=False))

# 上位 5 県の集中度
top5_share = sorted_d.head(5)['C3801'].sum() / d['C3801'].sum()
print(f'\nホテル数 上位 5 県の全国シェア: {top5_share:.3f}')

📤 実行結果:

ホテル密度 上位 5 県 (100万人あたり): Prefecture C3801 A1101 HotelPer1M 沖縄県 3339 1468000 2274.5 山梨県 1328 796000 1668.3 長野県 2578 2004000 1286.4 福井県 892 744000 1198.9 大分県 999 1096000 911.5 ホテル密度 下位 5 県: Prefecture C3801 A1101 HotelPer1M 千葉県 1238 6257000 197.9 大阪府 1576 8763000 179.8 愛知県 1208 7477000 161.6 神奈川県 1297 9229000 140.5 埼玉県 694 7331000 94.7 ホテル数 上位 5 県の全国シェア: 0.179

💬 結果の読み方: 沖縄・山梨・長野は人口あたりホテル数で上位、 都市部の埼玉・神奈川が下位。 「観光地県」と「住宅都市」という別軸が浮上。 名義変数「県名」は単なるラベルでも、 量的データと組み合わせると カテゴリ間の質的差異を浮き彫りにする。

挑戦課題

  1. 47 県を 5 地域 (北海道/東北/関東/中部/西日本) に再集約し、 χ² 検定で「観光地度合い (ホテル密度 上 / 中 / 下)」と関連があるか測れ。
  2. One-hot で 47 列を作り、 多重共線性チェック (VIF) を実行せよ。
  3. 都道府県名を 16 次元 Embedding に変換し、 PCA で 2D に圧縮した散布図で「似た県」を確認せよ。

⚠️ よくある落とし穴

この用語を使うときに陥りがちな失敗パターン。 経験者ほどここに 1 度はハマっています。

❌ 名義に平均を計算
「血液型の平均」は無意味だが、 数値化してしまうとエラーが出ずに進む。
❌ カテゴリの順序を恣意的に決定
都道府県コードの大小に意味はない。
❌ One-Hot 次元爆発
カテゴリ数が多いと次元が増える。 Target Encoding を検討。
❌ Tree モデルでは不要なこと
決定木は数値カテゴリを順序で扱うが、 ラベルエンコーディングは Tree でしか使えない。

⚠️ 名義尺度を扱うときの 8 大落とし穴 (詳説)

  1. カテゴリコードを数値特徴に流す: 「東京=1, 北海道=2, ...」と整数を機械学習モデルに入れると、 線形回帰やニューラルネットは「東京の 2 倍 = 北海道」と読みます。 木モデル以外で OrdinalEncoder を使うときは要注意。
  2. JIS 都道府県コードの大小に意味を持たせる: SSDSE 系で「都道府県コード」順に並べると北から南へ並ぶ慣習がありますが、 これは「順序尺度」ではなく「行政上の伝統」です。 因果モデルで「コード上位の県は…」と論じてはいけません。
  3. One-Hot 後にスケーリング: StandardScaler を 0/1 ダミー列に適用しても害は少ないが、 解釈性が損なわれます。 ダミー列は基本的にスケーリング対象外にすべきです。
  4. カイ二乗検定の期待度数 5 未満: 名義 vs 名義のクロス集計で期待度数が 5 未満のセルが多いと、 $\chi^2$ 近似が不正確になります。 Fisher の正確検定や Monte Carlo p-value に切り替えてください。
  5. レアカテゴリの暴走: 47 都道府県の中で「沖縄」だけが特殊な振る舞いをするとき、 One-Hot だと係数が極端に振れます。 Target Encoding の Smoothing で平滑化するか、 「沖縄+九州」とまとめます。
  6. 欠損値を別カテゴリにしない: 名義列に NaN がある場合、 「欠損」自体が情報を持つことが多い (例:未記入は無回答層に偏る)。 dropna ではなく「__missing__」カテゴリにする方が情報損失が少ない。
  7. Train/Test 間のカテゴリ不一致: 訓練時に出ていない都道府県が検証時に出ると、 One-Hot Encoder はエラー。 handle_unknown='ignore' を明示。
  8. 可視化での順序の押し付け: matplotlib の棒グラフでアルファベット順 / コード順に並べると視覚的に「順序がある」と錯覚させます。 頻度降順 (Pareto) で並べるのが正解。

🎓 拡張 deep-dive:名義尺度を巡る 5 つのテーマ

テーマ 1:Stevens 分類への批判と現代的拡張

Stevens (1946) の 4 分類は教育上わかりやすい一方、 統計学者 Velleman & Wilkinson (1993) は「実際にはデータの尺度は使用文脈で決まる」と批判しました。 たとえば「血液型」を名義として頻度集計するのは妥当でも、 「血液型 → 性格」を予測する文脈では因果的構造を持ち得ます。 Mosteller & Tukey (1977) は 名義 / 階級 / 順位 / 数 / カウント / 量 / 平衡 の 7 分類を提案。 現代では「テンソル尺度」「グラフ尺度」など機械学習用の拡張が進んでいます。

テーマ 2:エントロピー測度

名義データの「ばらつき」を測るには、 分散ではなく シャノンエントロピー $H = -\sum_k p_k \log p_k$ を使います。 全カテゴリが等確率のとき最大 ($H = \log K$)、 一つに集中すれば 0。 SSDSE-B-2026 の「都道府県」列はサンプリングが均一なので $H = \log 47 \approx 3.85$ nat。 一方、 もし「東京」の出現頻度が 80% なら $H \approx 0.50$ nat と急減します。 この値は「カテゴリ間の情報量」を表す Gini 不純度や Theil の指標とも関連します。

テーマ 3:エンコーディング戦略の比較

手法カテゴリ数の許容木モデル線形モデルニューラルネット主な落とし穴
One-Hot数十まで次元爆発
Ordinal (label)何でも順序の誤導入
Target Encoding数百〜数千リーク
Frequency Encoding数百〜数千頻度=効果と誤認
Embedding (学習)数千〜数万訓練データ依存
CatBoost native数千--ライブラリ依存

テーマ 4:類似度の定義

名義データの間に「距離」は本来存在しません。 強いて定義するなら、 単純一致係数 (SMC) $\text{SMC}(x, y) = \frac{1}{p}\sum_j \mathbb{1}[x_j = y_j]$ や、 Jaccard 係数があります。 多変量名義データのクラスタリングでは k-modes が標準。 都道府県を地域 (北海道・東北・関東…) でグループ化する場合は、 地理的近接性を別途付与する必要があります。

テーマ 5:因果推論との接続

交絡因子が名義変数 (例:「都道府県」) のとき、 層別解析や Mantel-Haenszel 推定量で因果効果を推定します。 単純な調整変数として線形回帰に入れる際は One-Hot にしますが、 47 都道府県すべての固定効果を推定するには各層に十分なサンプルが必要 ── そうでなければ Random effects (混合効果モデル) に変更します。

❓ 深掘り FAQ — 名義尺度

Q. 都道府県を「東日本/西日本」の 2 値にしても名義?
はい。 2 カテゴリ名義は 二値名義 (binary nominal) です。 これは事実上ベルヌーイ分布として扱え、 比率検定が適用できます。
Q. 郵便番号は名義?順序?
郵便番号自体は名義ですが、 上位 3 桁は地理的なまとまりを反映するため、 地域フィーチャーとして利用できます ── ただしモデルで「数値」として扱うのは禁止。
Q. テストデータに新カテゴリが出てきたら?
scikit-learn の OneHotEncoder で handle_unknown='ignore' を指定。 LightGBM では訓練時に「未知カテゴリ用の枠」を持たせます。
Q. 名義尺度同士の関係を見るには?
クロス集計表+カイ二乗独立性検定。 効果量は Cramér V。 高次元では多重対応分析 (MCA)。
Q. 「順位を表す数値」は順序尺度。 では「票数」は?
票数自体は比例尺度 (絶対 0 あり、 差・比が意味を持つ)。 順位だけ取り出せば順序尺度。 尺度は表現する数値の意味で決まります。

⚠️ 名義尺度 7 大落とし穴

  1. 順序があるかのように扱う: 「血液型 A=1, B=2, O=3, AB=4」と Label Encoding して線形回帰に投入 → 暗黙の順序仮定。 学番号も同様。
  2. 平均を計算する: 「東京都=1, 大阪府=2, ... の平均 24」は意味なし。 都道府県名から平均 / 標準偏差は計算不可。
  3. ダミー変数トラップ: One-hot 全列を回帰に入れると完全多重共線性 → 1 列削除 (drop_first=True) すること。
  4. カテゴリ数爆発: 47 県だけならまだしも、 都道府県 × 市区町村 = 1700 カテゴリだと One-hot で次元爆発。 Embedding か frequency 集約を検討。
  5. 低頻度カテゴリ: テストデータに学習時に無いカテゴリが現れると OneHot は 0 ベクトル化。 「その他」カテゴリへ集約 + handle_unknown='infrequent_if_exist' で対応。
  6. Target Encoding のリーケージ: 全データの平均を使うと test 情報が train に漏れる → out-of-fold target encoding が必須。
  7. Cramér's V を相関係数のように使う: V は名義変数の関連度合いだが、 線形性ではなく独立性の指標。 「V=0.5 なので予測できる」は誤解。 連続変数とは別概念。

🏢 業界別: 名義尺度の典型変数

領域名義変数カテゴリ数推奨符号化
医療血液型 (A/B/O/AB)4One-hot
医療ICD-10 病名コード~14,000階層集約 + Embedding
商業商品 SKU数万-数百万Embedding (Matrix Factorization)
商業地域 (都道府県)47One-hot or Target
ウェブUA / ブラウザ数十One-hot
ウェブURL ドメイン数百万Hashing trick
バイオSNP (AA/AG/GG)3One-hot or Label (3 = 加算的)
金融業種コード数百階層 + Target Encoding

🎮 触って理解する

血液型 (A・B・O・AB) を例に、 名義尺度で許される操作だけを体感します。 各カテゴリの度数をスライダーで変える、 または棒を上下にドラッグ (タッチ可) すると、 棒グラフ・度数・割合・最頻値がリアルタイムに更新されます。 名義尺度でできるのは「等しいか異なるかの判定」と「度数集計・最頻値」だけ。 平均・中央値・順序付けは無意味であることを、 実際に計算して確かめます。

度数

棒を上下ドラッグ、 または下のスライダーで度数を変更

✅ 名義尺度で意味のある値
血液型度数割合
合計 N
最頻値 (mode):
❌ 計算できても無意味な値

便宜的に A=1, B=2, O=3, AB=4 と数値を割り当てて平均・中央値を計算します。

数値ラベルの平均:
数値ラベルの中央値:

ここがポイント: 度数と最頻値は「どのラベルが多いか」というデータそのものの性質なので、 数値の割り当て方を変えても不変です。 一方、 平均・中央値は「A=1, B=2…」という恣意的な番号に依存し、 付け替えボタンを押すと同じデータなのに値が変わってしまいます。 数値が変わる=その量には意味がない、 という証拠です。 名義尺度では最頻値・度数・割合だけを使いましょう。

📊 尺度水準の対比

尺度 等 / 不等 順序 (< >) 差 (−) 比 (÷) 代表値
名義血液型・都道府県名最頻値
順序満足度 1〜5・順位中央値
間隔気温 °C・西暦算術平均
人口・面積・所得幾何平均も可

上の表の通り、 名義尺度で許されるのは「等 / 不等の判定」だけ。 順序 (順序尺度) 以上でしか大小比較は意味を持たず、 差 (間隔尺度)・比 (比尺度) と情報が積み上がっていきます。 名義データの代表値は必ず最頻値を使ってください。

🧭 さらに理解を深める

🎨 直感
名義尺度は「順序も間隔もないただのラベル」。 A・B・O・AB は名前が違うだけで、 「A は B より大きい / 小さい」も「A と B の間隔」も存在しません。 区別 (= / ≠) がつくこと、 それだけが情報です。
🕳️ よくある落とし穴
カテゴリに振った数値ラベルを量として扱う誤り。 「A=1, B=2…」の平均や、 One-hot せずコードのまま線形回帰・NN に入れると、 モデルは「AB は A の 4 倍」と誤解します。 木モデル以外でのラベルエンコーディングは要注意。
🚀 発展
Stevens の4 つの尺度水準 (名義 ⊂ 順序間隔) の最下層。 機械学習では順序を仮定しないOne-hot エンコーディングや Target Encoding で数値化し、 関連の検定にはカイ二乗検定・Cramér V を使います。

🗺 概念マップ — 名義尺度を中心に

この概念は単独で存在するものではなく、 周辺の用語と包含・対比・派生の関係で結ばれています。 中心に置いて、 矢印が伸びる先のページをリンクから辿ってみてください。

📊 ケーススタディ:47 都道府県を 8 地域に集約する

SSDSE-B-2026 の「都道府県」名義変数を、 地理的近接性に基づき8 地域 (北海道・東北・関東・中部・近畿・中国・四国・九州沖縄) に集約することで、 One-Hot 列を 47 → 8 に圧縮できます。 これは情報損失と引き換えにモデル汎化性能の向上を狙う典型的なテクニックです。

集約の妥当性は、 各地域内の都道府県が共通の特性 (気候・産業構造・人口密度) を持つかで決まります。 たとえば「製造業比率」を予測する場合、 関東・中部の自動車産業集積を考慮すれば 8 地域集約は理にかなう。 逆に「気候適応性」を予測するなら、 沖縄を「九州」に含めるのは粗すぎ ── 別ラベルを与えるべきです。

📥 入力例(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
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
# 地域マッピング辞書(47 都道府県 -> 8 地域)
region_map = {
    '北海道': '北海道',
    '青森県': '東北', '岩手県': '東北', '宮城県': '東北', '秋田県': '東北', '山形県': '東北', '福島県': '東北',
    '茨城県': '関東', '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東', '東京都': '関東', '神奈川県': '関東',
    '新潟県': '中部', '富山県': '中部', '石川県': '中部', '福井県': '中部', '山梨県': '中部', '長野県': '中部', '岐阜県': '中部', '静岡県': '中部', '愛知県': '中部',
    '三重県': '近畿', '滋賀県': '近畿', '京都府': '近畿', '大阪府': '近畿', '兵庫県': '近畿', '奈良県': '近畿', '和歌山県': '近畿',
    '鳥取県': '中国', '島根県': '中国', '岡山県': '中国', '広島県': '中国', '山口県': '中国',
    '徳島県': '四国', '香川県': '四国', '愛媛県': '四国', '高知県': '四国',
    '福岡県': '九州沖縄', '佐賀県': '九州沖縄', '長崎県': '九州沖縄', '熊本県': '九州沖縄', '大分県': '九州沖縄', '宮崎県': '九州沖縄', '鹿児島県': '九州沖縄', '沖縄県': '九州沖縄'
}
df['地域'] = df['Prefecture'].map(region_map)
# 地域別人口集計
print(df.groupby('地域')['A1101'].mean().sort_values(ascending=False))
# One-Hot 化
X_full = pd.get_dummies(df[['Prefecture']], prefix='pref')   # 47 列
X_region = pd.get_dummies(df[['地域']], prefix='reg')     # 8 列
print('Full:', X_full.shape, ' Region:', X_region.shape)
📤 実行例(実測) 地域 関東 6.179970e+06 北海道 5.297196e+06 近畿 3.200809e+06 中部 2.364187e+06 九州沖縄 1.792087e+06 中国 1.466696e+06 東北 1.463972e+06 四国 9.419939e+05 Name: A1101, dtype: float64 Full: (564, 47) Region: (564, 8)

列数を 47 → 8 に減らせば、 線形回帰・MLP では過学習が軽減されます。 木モデルは元々分割で対応するため、 集約効果は限定的。 タスクとモデルの組合せで判断します。

nominal scale 2 値 (Binary / 多値名義 (Multinom 順序名義 (Ordered 循環カテゴリ (Cyclic 階層カテゴリ (Hierar 高次カテゴリ (High-c

🔗 隣接 隣接手法への橋渡し

「nominal scale」を中心に、 隣接する手法・概念との関係を以下に整理する。 単独の手法理解にとどまらず、 分析パイプライン全体での位置付けを把握することで、 適切な前段・後段・代替手法を選べる。

隣接手法関係接続のポイント
2 値 (Binary / Dichotomous)上位 / 一般化「nominal scale」と組み合わせる/比較する場面で参照
多値名義 (Multinomial)下位 / 特殊化「nominal scale」と組み合わせる/比較する場面で参照
順序名義 (Ordered Nominal)並列 / 対比「nominal scale」と組み合わせる/比較する場面で参照
循環カテゴリ (Cyclic)前段 (前処理)「nominal scale」と組み合わせる/比較する場面で参照
階層カテゴリ (Hierarchical)後段 (後処理)「nominal scale」と組み合わせる/比較する場面で参照
高次カテゴリ (High-cardinality)評価 / 比較「nominal scale」と組み合わせる/比較する場面で参照

名義尺度は「区別だけ意味を持つ」最も情報量の少ない尺度。 SSDSE-B-2026 の「都道府県名」「地域区分」が典型で、 平均や順位は意味を持たず、 最頻値・度数・カイ二乗検定が分析の中心になる。

🌳 手法選択フロー

名義尺度データには「順序・量を持たない」前提で分析手法を絞る。

  1. 代表値を求めたい 最頻値のみ意味を持つ (平均・中央値は使えない)
  2. 2 変数の関連を見る カイ二乗検定 / Fisher の正確検定 / Cramér V を使う
  3. 機械学習の入力にする ワンホット符号化 / target encoding で数値化

SSDSE-B-2026 の都道府県名はそのまま投入せず、 地域区分でグループ化するか、 ターゲットエンコーディングで数値化してから回帰や分類モデルに入れる。

🔎 解説を深掘りする ── 名義尺度で許される唯一の関係は「同値(=/≠)」だけ

本ページの他の節は「名義データをどう集計し、 関連(カイ二乗・Cramér V)をどう測るか」を扱った。 ここでは一歩手前に戻り、 名義尺度でそもそも何が許される演算なのかという原点を独自角度で深掘りする。 結論を先に言うと、 名義尺度で定義される関係は「2つの値が同じか違うか(=/≠)」ただ一つだけであり、 大小(</>)も差(−)も比(÷)も一切定義されない。 数字に見えても、 それは「並べ替えてもよいラベル」に過ぎない。 姉妹ページの 尺度水準 が4尺度の全体像を、 順序尺度 が「大小は使えるが差は使えない」段階を扱うのに対し、 本節は名義尺度に固有の「同値だけ」という最下段の性質を、 都道府県コードという“数値に見える名義データ”で実証する。

🎨 直感

SSDSE-B-2026 の Code 列(例: 北海道=R01000、 沖縄県=R47000)は、 見た目こそ 01〜47 の連番だが、 これは JIS の全国地方公共団体コードで、 北東から南西へという地理的な並べ方の“規約”にすぎない。 番号が大きいほど人口が多い・面積が広い、 といった測定可能な量とは無関係だ。 実際、 2023 年・47 都道府県で Code の番号部分(01〜47)と総人口 A1101 の相関を測ると、 Pearson で −0.24、 Spearman で −0.29(実測値)。 ほぼ 0 に近く、 番号の大小が量の情報をほとんど持たないことがはっきり分かる。 番号は「住所ラベル」であって「ものさしの目盛り」ではない、 というのが名義尺度の直感だ。

⚠️ 落とし穴(重要)── 「番号で並べ替えたら順番が出た」は測定ではなく規約

名義コードは数値型で格納されることが多いため、 sort するともっともらしい“順番”が出てしまい、 順序尺度・間隔尺度だと錯覚しやすい。 Code 昇順は 北海道(01)→青森(02)→岩手(03) … 宮崎(45)→鹿児島(46)→沖縄(47) と北から南へきれいに並ぶが、 これは地理規約が生んだ見かけの順序で、 何かの大きさを表す順序ではない。 決定的な反例が人口だ。 最大人口の東京都はコード 13(真ん中あたり)、 最小人口の鳥取県はコード 31(実測値)。 量の最大・最小が番号列の“端”ではなく中ほどに散らばることこそ、 番号に大小の意味がない証拠である。

さらに注意したいのは、 前掲の相関がぴったり 0 ではなく −0.24 だった点だ。 これを「弱い負の傾向がある」と読むのは典型的な誤り。 コードを別規約(例: 五十音順やアルファベット順)で振り直せば、 同じデータでも相関値は別の数字に変わる。 付番の仕方しだいで動く相関は、 名義尺度では意味を持たない(本ページ「触って理解する」節の“番号を付け替えると平均が動く”実演と同じ論理を、 相関の側から見たものだ)。 名義データで許されるのは、 度数・割合・最頻値、 そして別の名義変数との関連(カイ二乗・Cramér V)まで。 平均・相関・回帰係数を番号に対して計算した瞬間、 それは規約という砂上に建てた楼閣になる。

# SSDSE-B-2026, 2023年, 47都道府県, 実測(cp932, skiprows=[1]) df['Code'].nunique() = 47 df['Prefecture'].nunique() = 47 # コード⇔県名は1対1 codenum = Code の01〜47(例 R13000→13, R31000→31) codenum.corr(A1101, 'pearson') = -0.2406 # 番号と人口はほぼ無相関 codenum.corr(A1101, 'spearman') = -0.2857 # 順位で見てもほぼ無相関 最大人口: 東京都 codenum=13 A1101=14,086,000 最小人口: 鳥取県 codenum=31 A1101= 537,000 # 量の最大最小は番号の中ほど Code昇順: 北海道(01)→青森(02)→岩手(03) … 宮崎(45)→鹿児島(46)→沖縄(47) # 地理規約

🚀 発展

「同値だけが許される」という制約は、 分析設計そのものを縛る。 (1) 要約統計量は最頻値のみ。 平均・中央値は名義尺度には定義されない(中央値は順序尺度以上で初めて意味を持つ)。 (2) “同じ”の判定基準が分析の全てを決める。 同値が唯一の演算である以上、 「2つの値を同一カテゴリと見なすか」の線引き――表記ゆれ・全角半角・前後の空白の正規化――でカテゴリ数(nunique)が水増し/統合され、 度数も割合も変わる。 SSDSE の Code は 47 でクリーンだが、 現場の名義データ(自由記述の職業名など)では前処理が結果を左右する。 (3) 機械学習では順序の誤混入に注意。 名義コードをそのまま整数特徴に使うと、 線形モデルは「13<31」というありもしない大小を学習してしまう。 だからこそ One-Hot エンコーディング(順序を持ち込まない)が名義尺度の基本形になる。 なお番号を数値のまま扱ってよい木系モデルでも、 それは「大小を使う」のではなく「分岐で同値グループを切り出す」動作であって、 名義尺度の原則と矛盾しない点は押さえておきたい。

🧭 関連ページ