# Tidy_rule — jp-election-data Schema Contract

Version: 0.6.0-public  
Date: 2026-03-19  
Scope: 2026-02-08 衆議院議員総選挙 比例代表ブロック（47都道府県）  
License: jp-election-data License v1.0

---

## §0. 目的と利用範囲

### §0.1 本文書の目的

本文書は、日本の公的選挙データを構造化された事実（Structured Facts）に変換するためのスキーマ契約である。

本データセットおよび本契約は、**公的選挙データの検証・分析・研究・報道・市民活動**に特化して設計されている。

### §0.2 設計上の前提と制約

本スキーマは以下の前提に基づいて設計されている。

- 入力は日本の選挙管理委員会が公開する一次資料（HTML / XLSX / PDF 等）である
- 出力は再実行可能なパイプラインで生成される CSV ファクトである
- 集計済みデータは意図的に含めない（leaf-level facts のみ）
- 辞書（dictionary）への依存が設計の中核にある

**警告: 本スキーマは多目的利用を想定していない。** 汎用データ分析ツール、商用 BI プラットフォーム、AI パイプラインの入力として使用した場合、以下の問題が発生する。

- 行政区分割行（白石区 / 白石区第1 / 白石区第2 等）の二重計上
- party_id がコードであるため、辞書なしでは政党名が取得できない
- municipality_name の名寄せが不完全な集計結果を生む
- 集計済み行（札幌市 = 区の合算）と leaf 行の混在による重複

これらは欠陥ではなく、正確な選挙データ分析に必要な粒度を維持するための設計判断である。

### §0.3 AI による利用に関する注意

本データセットを AI ツールで処理する場合、以下の条件を満たすこと。

- 本文書（Tidy_rule）を事前にコンテキストとして読み込むこと
- party_master.csv および area 辞書を結合してから分析すること
- §4 の行政区分割ルールを理解してから集計すること
- 集計結果を fact_district_stats の valid_votes と照合すること

**本文書を読み込まずにデータのみを処理した場合、構造的に不正確な結果が生成される。** これは AI の性能の問題ではなく、データが目的特化で設計されているためである。

### §0.4 公開後査読

本データセットの公開プロセスは、**公開前に exhaustive な人手監査を完了させること** を前提にしていない。

代わりに、以下の順序を設計として採る。

1. 一次資料から Layer 2 facts を構築し、機械検証と公開可能な整合性チェックを通す
2. current release を公開する
3. 公開後に人間査読・独立確認・差分報告を受ける
4. 必要に応じて residual 開示・版更新・再生成を行う

したがって、`公開済み` は `全件人手確認済み` を意味しない。公開後査読は例外処理ではなく、設計上の正式な後段プロセスである。

---

## §1. ファクト定義

本データセットの正本は 2 つの CSV ファクトである。

### §1.1 fact_candidate_votes

政党 × 市区町村の得票数を記録する。

| 列名 | 型 | 必須 | 説明 |
|---|---|---|---|
| election_date | date | Y | 選挙執行日（ISO 8601） |
| election_type | string | Y | `hr` = 衆議院 |
| vote_system | string | Y | `block` = 比例代表ブロック |
| prefecture_code | string | Y | 2桁の都道府県コード（文字列。01〜47） |
| prefecture_name | string | Y | 都道府県名 |
| jis_code | string | Y | 全国地方公共団体コード（6桁文字列） |
| municipality_name | string | Y | 市区町村名（§4 参照） |
| district | string | N | 小選挙区名（block では空） |
| district_magnitude | integer | N | 定数（block では空） |
| pr_block | string | Y | 比例代表ブロック名 |
| candidate_name | string | N | 候補者名（block では空） |
| candidate_name_kana | string | N | 候補者名かな（block では空） |
| candidate_gender | string | N | 性別（block では空） |
| candidate_age | integer | N | 年齢（block では空） |
| candidate_status | string | N | 現職/新人等（block では空） |
| party_id | string | Y | 政党コード（§2 参照） |
| votes | integer | Y | 得票数 |
| is_elected | boolean | N | 当選フラグ |
| election_result | string | N | 選挙結果 |

**注意:** `prefecture_code` は文字列型である。数値型として扱うと `01`（北海道）が `1` になり、辞書結合が破壊される。

**注意:** `party_id` は正式政党名ではない。`LDP`, `CDR`, `DPP` 等のコードであり、party_master.csv との結合が必須である。コードのみで分析を行うと、読み手に対して政党名が伝わらない。

### §1.2 fact_district_stats

市区町村ごとの投票統計を記録する。

| 列名 | 型 | 必須 | 説明 |
|---|---|---|---|
| election_date | date | Y | 選挙執行日 |
| election_type | string | Y | 選挙種別 |
| vote_system | string | Y | 投票制度 |
| prefecture_code | string | Y | 都道府県コード |
| prefecture_name | string | Y | 都道府県名 |
| jis_code | string | Y | 全国地方公共団体コード |
| municipality_name | string | Y | 市区町村名 |
| district | string | N | 小選挙区名 |
| district_magnitude | integer | N | 定数 |
| pr_block | string | Y | 比例代表ブロック名 |
| eligible_voters | integer | Y | 有権者数 |
| actual_voters | integer | Y | 投票者数 |
| valid_votes | integer | Y | 有効投票数 |
| invalid_votes | integer | Y | 無効投票数 |

### §1.3 2ファクト間の整合性

以下の算術整合が常に成立しなければならない。

- `actual_voters = valid_votes + invalid_votes`（fact_district_stats 内）
- `SUM(votes) WHERE jis_code = X = valid_votes WHERE jis_code = X`（2ファクト間）

**この整合性チェックは、データ利用者が最初に実行すべき検証である。** 整合しない場合、パイプラインまたはソースデータに問題がある。

---

## §2. 辞書依存

本データセットは辞書なしでは正しく利用できない。これは意図的な設計である。

### §2.1 party_master.csv

| 列名 | 説明 |
|---|---|
| party_id | 政党コード（ファクトの結合キー） |
| formal_name | 正式名称 |
| short_name | 略称 |
| english_name | 英語名 |

party_id はファクト CSV 内で一貫して使用される。正式名称への変換は常にこの辞書を経由する。

### §2.2 area_master.csv / area_alias.csv

市区町村の正規化名と JIS コードの対応。ソースごとの表記揺れ（「さいたま市」「ｻｲﾀﾏ市」等）は area_alias.csv で吸収される。

**警告:** area_alias を経由せずに municipality_name で直接結合した場合、表記揺れにより結合漏れが発生する。結合キーには jis_code を使用すること。

### §2.3 scope_master.csv / region_block_master.csv

「全国」「全国区」「地方」「県」「市町村」等のスコープ語、および「北海道」「東北」等の地方ブロック名の正規化辞書。

---

## §3. 四層モデル

データの生成と公開は以下の四層で管理される。

| 層 | 名称 | 内容 | 公開 |
|---|---|---|---|
| Layer 0 | Evidence | 一次資料（HTML/XLSX/PDF）+ source.yaml | 非公開 |
| Layer 1 | Internal Model | 中間変換物（M0〜M3b） | 非公開 |
| Layer 2 | Release Facts | 2ファクト CSV + 辞書 | **公開** |
| Layer 3 | Deliverables | スプレッドシート・可視化等 | 一部公開 |

**原則:** 上位層から下位層を生成する。下位層から上位層へ値を戻さない。

本リポジトリで公開されるのは Layer 2 の Release Facts と辞書、および Layer 3 の一部（public-summary CSV、検証成果物）である。

Layer 0 の一次資料は各都道府県選挙管理委員会の公式サイトに所在する。source.yaml にソース URL と取得日時を記録しているが、一次資料そのものは本リポジトリに含めない。

---

## §4. 行政区分割ルール

**これは本データセットを正しく利用するための最重要ルールである。**

一部の政令指定都市では、選挙区の境界が行政区と一致しない。この場合、同一の行政区が複数の行に分割される。

例: 北海道 札幌市白石区

```
jis_code  municipality_name  votes(LDP)
011045    白石区              30563      ← 白石区全体の集計行
011045    白石区第1           27948      ← 小選挙区A に属する部分
011045    白石区第2            2615      ← 小選挙区B に属する部分
```

**白石区 + 白石区第1 + 白石区第2 を合算してはならない。** 白石区は白石区第1 + 白石区第2 の合算結果である。つまり leaf 行は「白石区第1」「白石区第2」であり、「白石区」は集計行である。

このパターンは全国の政令指定都市に存在する（札幌、仙台、さいたま、千葉、横浜、川崎、相模原、新潟、静岡、浜松、名古屋、京都、大阪、堺、神戸、岡山、広島、北九州、福岡、熊本）。

**集計時の安全な手順:**
1. municipality_name に「第1」「第2」等の接尾辞があるかを検査する
2. 接尾辞がある行（leaf 行）のみを使用して集計する
3. 接尾辞がない同名行（集計行）は除外する
4. 集計行が存在しない市区町村は、その行自体が leaf 行である

**多目的利用でこのルールを無視した場合、得票数が最大で2倍に膨れる。** これはデータの欠陥ではなく、選挙データの実態を正確に反映した構造である。

---

## §5. 推論禁止ルール

以下の値は、AI・人間を問わず、推論・補間・外挿で生成してはならない。

- `election_date`: ソース文書から明示的に取得する
- `election_type`: ソース文書から明示的に取得する
- `vote_system`: ソース文書から明示的に取得する
- `pr_block`: 公式のブロック区分表から取得する
- `votes`: ソース文書の数値をそのまま転記する
- `jis_code`: 公式の全国地方公共団体コード表から取得する

推論禁止の値が取得できない場合は `__MISSING__` を設定する。空文字列や推定値を入れてはならない。

---

## §6. ソースの真正性

### §6.1 canonical source の定義

データの正本ソースは、各都道府県選挙管理委員会が公式サイトで公開する選挙結果である。報道機関のデータ、Wikipedia、選挙情報サイト等は canonical source ではない。

### §6.2 source.yaml

各 election の internal `source.yaml` には、取得元 URL、exact fetch time、形式、variant_key を記録する。

公開用の source register では exact fetch time は落とし、`source_url`, `source_format`, `file_hash_sha256` を中心に公開する。exact fetch time は internal provenance register のみに残す。

### §6.3 同一選挙の複数ソース

同一の election に対して複数の公式ソースが存在する場合（例: 和歌山県の PDF 版と Excel 版）、それぞれを variant として管理し、Layer 2 facts が一致することを検証する。

---

## §7. 検証

### §7.1 内部整合性

- `actual_voters = valid_votes + invalid_votes`
- `SUM(votes) = valid_votes`（同一 jis_code 内）
- `__PENDING__ = 0`（すべての仮値が解消されていること）
- `__MISSING__ = 0`（results 系。turnout 系は別途記録）

### §7.2 外部整合性

- 総務省が公開するブロック別集計値との突合（verify_soumu_block_aggregates）
- 各都道府県の公式集計値との突合（verify_official_aggregate_totals）

### §7.3 既知の残差

以下の残差は分類済みであり、本データセットの公開時点で未解消である。

- 近畿ブロックの microdiff（小数点以下の端数処理差異）
- 北関東・四国の overseas-turnout scope delta（在外投票のスコープ差）
- 一部県の invalid-only diff（無効票のみの差異）
- 奈良県の aggregate-row drift（9 area の報告値差異）

これらは verification/ ディレクトリに詳細を記録している。

---

## §8. 公開範囲

本リポジトリで公開されるもの:

- Layer 2 Release Facts（fact_candidate_votes.csv / fact_district_stats.csv × 47 election）
- common dictionary（party_master / area_master / area_alias / scope_master / region_block_master 等）
- 本文書（Tidy_rule）および関連 SPEC
- 検証成果物（verification/）
- 最小再実行パイプライン（pipeline/）

本リポジトリで公開されないもの:

- Layer 0 の一次資料そのもの（ソース URL は source.yaml に記録）
- Layer 1 の中間変換物
- 運用ログ・判断記録・学習層
- AI orchestration protocol

---

## §9. この文書を読まずにデータを使った場合に起きること

以下は、本文書を読まずにデータを処理した場合に発生する典型的な問題の一覧である。

| 問題 | 原因 | 参照 |
|---|---|---|
| 得票数が公式値の約2倍になる | 行政区分割行の二重計上 | §4 |
| 政党名が表示されない | party_id が辞書依存のコード | §2.1 |
| 北海道の prefecture_code 結合が失敗する | `01` を数値 `1` として扱った | §1.1 |
| 市区町村の結合で欠損が出る | municipality_name の表記揺れ | §2.2 |
| 投票率の計算が合わない | 在外投票のスコープ差 | §7.3 |
| 集計値が fact_district_stats と一致しない | 集計行と leaf 行の混同 | §4 |

**これらはすべて、本文書の該当セクションを事前に読んでいれば回避できる。**

---

## 改訂履歴

| 版 | 日付 | 内容 |
|---|---|---|
| 0.6.0-public | 2026-03-19 | 公開用に再構成。§0（目的と利用範囲）、§9（警告一覧）を追加。内部参照を除去 |
