論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
名寄せ
Name Resolution / Entity Matching
データ前処理

🔖 キーワード索引

名寄せ (Name Resolution / Entity Resolution / Record Linkage) は、 表記が異なるが同じ実体を指すレコードを束ねる作業。 SSDSE-B-2026 と外部データを結合する際の必須前処理。

🎨 直感 📐 数式 🔬 数式を言葉で読み解く 🧮 実値で計算 🐍 Python 実装 ⚠️ 落とし穴 🌐 関連手法 📍 文脈 📚 関連教材 クレンジング カテゴリ変数

💡 30秒で分かる結論

🍰 まずはやさしく

バラバラな名前を一つにまとめる作業です。

データの重複をなくすために使います。

同じお店なのに書き方が違う場合などに便利です。

この章では名寄せのやり方を学びます。

重複する人物・組織を統合する処理

💡 クイック Tips 10 選

  1. 最初に必ず unicodedata.normalize('NFKC', s) を実行
  2. 大文字小文字は .upper() で統一
  3. 前後空白は .strip()
  4. 正規化辞書は JSON で管理、 Git にコミット
  5. 類似度閾値は正解データで F1 を測って決める
  6. 結合後は必ず件数を確認 (期待値との差を確認)
  7. 名寄せの結果に元レコード ID と信頼度を残す
  8. 大規模ならブロッキング (rapidfuzz + 接頭辞)
  9. 個人情報なら法的要件 (個人情報保護法・GDPR)
  10. 機械学習は「ルールベースで限界に達してから」検討

🌍 名寄せが活躍する応用領域

名寄せは「データを 1 つにする」基礎技術として、 ほぼあらゆるデータ駆動の場面で隠れた基盤になっている。

📊 ベンチマーク: ライブラリ別性能

10 万件 × 10 万件の文字列ペアを類似度計算した場合の参考タイム (CPU シングルスレッド、 文字列長 5-20 文字を想定)。

ライブラリ関数1 万ペア時間特徴
difflib (標準)SequenceMatcher2-3 秒Pure Python、 小規模向け
fuzzywuzzyfuzz.ratio1-2 秒python-Levenshtein 併用
rapidfuzzfuzz.ratio0.05 秒C++ 実装、 30-60 倍速
jellyfishjaro_winkler0.1 秒C 実装
recordlinkageindexer + comparerパイプラインブロッキング込み

SSDSE-B-2026 級 (47 件) ならどれでも瞬時。 大規模では rapidfuzz が事実上の標準。

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

🍰 まずはやさしく

データの整理整頓のような作業です。

正しい集計結果を出すために使います。

アンケートの回答者が重複している時に役立ちます。

名寄せがどのような位置づけかを確認しましょう。

「同じ会社のはずなのに別レコードで集計されてしまう」「アンケート回答者の重複が判定できない」 — そんな問題を解くための前処理です。

📍 文脈ボックス

あなたが今見ているのは 「名寄せ (Name Resolution / Entity Resolution)」 のページです。 異なるソースのレコードが「同じ実体を指す」ことを判定し、 統合する作業。 統計分野では Record Linkage、 機械学習分野では Entity Resolution と呼ばれることが多い。 上位概念は データ前処理 > データクレンジング、 並列概念は データ統合・ 重複排除。 統計・データ解析コンペでは SSDSE-B-2026 の都道府県名と、 外部公開データの自治体名表記揺れを束ねる前処理 として日常的に登場する。

🎨 直感で掴む

🍰 まずはやさしく

人間には同じに見えても、機械には違う文字に見えます。

表記のゆれを統一して正しく判定するために使います。

「東京」と「東京都」を同じものとして扱う例です。

どのようにして名前を統合するかを考えます。

顧客リストに:

  • 「株式会社ABC」
  • 「(株)ABC」
  • 「ABC Co., Ltd.」
  • 「ABC」

これらは全部同じ会社 — 人間なら一目で分かるが、 計算機にはバラバラに見える。 これを 正規化+類似度判定 で統合するのが名寄せです。

名寄せは「(1) 文字列正規化 → (2) ブロッキング (候補絞り込み) → (3) ペアワイズ類似度算出 → (4) 閾値またはクラスタリングで同一判定」の 4 段で動く。 SSDSE-B-2026 の都道府県名は表記揺れが少ないが、 「東京都/東京/トウキョウ/Tokyo」のような複数表記を統一する処理が、 県をキーに別データ (経産省・厚労省の地域統計) と結合する際に必須になる。

類似度計算は Levenshtein 距離・Jaro-Winkler・コサイン類似度 (TF-IDF) ・埋め込みベクトル類似度などを使う。 「(株)ABC」と「ABC Co., Ltd.」のような対では、 法人語彙辞書で語幹を抽出してから比較するルールベース手法が、 単純な文字距離より精度が高い。

次節以降では、 SSDSE-B-2026 の県名と「東京/Tokyo/TKY」のような揺れた表記を題材に、 正規化 → Jaro-Winkler 算出 → 閾値判定の手計算 → Python (jellyfish / rapidfuzz) での再現を順に追う。

🎮 触って理解する:文字列類似度と閾値で「同一 / 別人」を判定する

名寄せの核心は 「表記の揺れを吸収して同一性をスコア化し、 閾値で線を引く」ことです。 ここでは架空の氏名・住所レコード対(表記ゆれ入り)について、 編集距離(レーベンシュタイン)から正規化類似度 sim = 1 − d / max(|A|,|B|) を実際に計算します。 閾値スライダーを動かすと同一 / 別人の判定が切り替わり、 正規化 ON/OFF で一致率が激変する様子を体感できます。

0.0 何でも同一視1.0 完全一致のみ
全角半角・半角カナ・(髙→高 / 邊→辺) などを統一

● 緑=本当は同一 / ● 赤=本当は別人。 縦線が閾値(ドラッグでも動かせます)。 右側の網掛けが「同一と判定」される領域。

適合率 Precision
同一判定のうち正しい割合
再現率 Recall
本当の同一を拾えた割合
F1 スコア
適合率と再現率の調和平均
混同(TP/FP/FN/TN)
誤統合=FP / 取りこぼし=FN
# レコード A レコード B 編集距離 d 正規化類似度 sim 正解 判定 結果

🧭 3 つの実験で体で覚える

  1. 閾値を 0.4 まで下げる → 「山田次郎」まで「山田太郎」と同一視され 過剰統合(FP=誤統合)が発生。 適合率が下がる。
  2. 閾値を 1.0 近くまで上げる → 少しでも揺れた同一実体を別人扱いし 取りこぼし(FN)が増える。 再現率が下がる。
  3. 前処理 ON/OFF を切り替える → OFF だと「ABC商事↔ABC商事」「タナカ↔タナカ」の類似度が激減し、 同じ閾値でも取りこぼしが急増。 正規化が名寄せの土台だと分かる。
💡 直感
編集距離は「A を B にする最小の書き換え回数」。 それを長さで割って 0〜1 に正規化すれば、 揺れの大きさに依らず「どれくらい似ているか」を比較できる。 名寄せはこの連続スコアに閾値で線を引き、離散的な同一/別人へ落とす作業。
⚠️ 落とし穴
閾値のトレードオフに万能値はない:下げれば誤統合、上げれば取りこぼし。 同名異人(別人が高スコア=FP)と異名同人(同一が低スコア=FN)は文字距離だけでは分離不能。 さらに全ペア比較は O(n²) で n=10万なら約50億対。
🚀 発展
ブロッキングで候補を接頭辞やソートキーで絞り O(n²) を回避。 確率的レコードリンケージ(Fellegi-Sunter)は一致/不一致を尤度比で重み付け。 音の揺れには Soundex 等の音声類似も併用し、 補助キー(生年月日・住所)で FP を抑える。 → データクレンジング と連携。

📐 定義/数式

🍰 まずはやさしく

重複する人物や組織を一つにまとめる処理です。

データの正しさを証明するために使います。

スマホの連絡先で同じ人をまとめるイメージです。

名寄せの定義と計算方法について読みましょう。

名寄せName Resolution / Entity Matching):重複する人物・組織を統合する処理

【編集距離(Levenshtein)】
$$ d(s_1, s_2) = \min\{\text{insertions} + \text{deletions} + \text{substitutions}\} $$
$s_1$ を $s_2$ に変換するための最小編集操作数。 文字列類似度の基本指標。

🔬 記号・用語の読み解き

記号意味
$d$編集距離(小さいほど似ている)
正規化全角→半角、 大文字小文字、 (株)→株式会社、 空白除去
ブロッキング全件比較は $O(n^2)$ で重い → 候補絞り込み
閾値類似度がいくら以上なら同一とみなすか

🔬 詳細な解説(深掘り)

概念の本質

名寄せ(Name Resolution / Entity Matching)は、 単に用語の定義を覚えるだけでは本当には理解できません。 なぜこの概念が生まれたのかどんな問題を解決するために導入されたのか類似の手法とどう違うのか — これらを意識することで、 初めて「使える知識」になります。

数式や Python コードはあくまで 道具。 道具の使い方を覚える前に、 その道具で何をしたいか(目的) を明確にすることが、 データサイエンス学習の鉄則です。

他の概念との関係

この用語は、 単独で存在するわけではなく、 多くの関連概念とネットワークを形成しています。 上の「関連用語」セクションに挙げたリンク先を1つずつ辿ると、 全体像が見えてきます。 特に:

実務で気をつけるポイント

理論を学ぶことと、 実務で使えることは別物です。 公的統計(SSDSE、 e-Stat 等)の実データで実装・実験することで、 教科書だけでは見えない罠 に気付けます。 たとえば:

これらは 名寄せ に限った話ではなく、 データサイエンス全般に共通する作法です。 「落とし穴」セクションの内容と合わせて、 自分なりのチェックリストを作るとよいでしょう。

📊 評価・検証の視点

名寄せ を使った分析の 正しさを担保する ためには、 以下の観点で検証するのが定番です。

確認する点名寄せ で何を見るか
正規化漏れ全角/半角、 大小、 法人格表記の揺れ — 事前に統一を。
過剰統合「鈴木一郎」と「鈴木一朗」を同一視 → 誤統合のリスク。
計算量爆発n=10万の全比較は1兆ペア。 ブロッキングで絞る。
黒箱化ML名寄せの判定根拠を残さないと監査できない。
再現性同じデータ・同じコードで同じ結果が出るか。このページの ▶ 実行ボタンで確かめられます

💼 業界別の使われ方

名寄せ は分野横断で活躍する概念です。 業界別に見ると以下のような使われ方があります。

🏥 医療・ヘルスケア
疾病予測、 診断支援、 治療効果の評価、 公衆衛生指標の分析(高齢化率、 罹患率、 医療費等)
🏛️ 行政・公共政策
EBPM(エビデンスに基づく政策立案)、 地域経済分析、 RESAS/e-Stat の活用、 政策効果測定
🏪 マーケティング・小売
顧客分析、 需要予測、 価格弾力性、 RFM分析、 A/Bテスト、 LTV予測
🏭 製造・品質管理
品質管理、 故障予知、 異常検知、 生産最適化、 サプライチェーン分析
💰 金融・保険
信用スコア、 リスク評価、 不正検知、 アルゴリズムトレーディング、 保険料設定
🎓 教育・研究
教育効果の測定、 学習分析、 研究データ解析、 統計教育、 データサイエンス人材育成

📈 公的統計データ(SSDSE)での具体例

名寄せ を実際のデータで学ぶときは、 SSDSE(教育用標準データセット、 総務省統計局)が便利です。

これらは 統計センターの SSDSE ページ から CSV で直接ダウンロードできます。 上の Python コード例で data/raw/SSDSE-B-2026.csv としているのが、 まさにこれです。

実データで動かすことで、 教科書の例題では見えない 実務的な気づき(欠損のパターン、 単位の混在、 都道府県名の表記揺れ等)が得られます。

🔧 よくあるトラブルと対処

🐍 Python コードが動かない
→ Python 3.10+ と必要ライブラリ(pandas、 numpy、 scikit-learn 等)がインストール済みか確認。 pip install pandas numpy scikit-learn matplotlib で揃います。
📁 CSVファイルが読み込めない
→ ファイルパスを確認。 文字コードが utf-8 ではなく shift_jiscp932 の場合がある(古い日本の公的統計に多い)。 encoding='cp932' を試してください。
📐 数式が表示されない
→ ページが KaTeX を読み込んでいるはずです。 ブラウザのキャッシュをクリアするか、 開発者ツールで JavaScript エラーを確認。
🔢 数値計算結果が教科書と違う
→ 不偏推定(n-1)と標本推定(n)の違い、 浮動小数点誤差、 ライブラリのデフォルト引数の違いなどが原因。 ドキュメントを確認。
📊 グラフが描画されない
→ Jupyter Notebook なら %matplotlib inline、 スクリプト実行なら plt.show() を忘れずに。 日本語フォントは matplotlib 用に別途設定(japanize-matplotlib 等)が必要。

🔬 数式を言葉で読み解く

名寄せの中核は「2 つの文字列がどれだけ似ているか」を数値化する 類似度関数 である。 代表的な 3 種を、 記号 → 言葉の順で読み解く。

編集距離 (Levenshtein Distance)

$$ d(a,b) = \min(\text{挿入} + \text{削除} + \text{置換}) $$

Jaccard 係数 (集合類似度)

$$ J(A,B) = \frac{|A \cap B|}{|A \cup B|} $$

コサイン類似度 (ベクトル類似度)

$$ \cos(\vec{u},\vec{v}) = \frac{\vec{u} \cdot \vec{v}}{\|\vec{u}\|\,\|\vec{v}\|} $$

これら 3 関数を組み合わせ、 閾値を設定して「同じか否か」を判定するのが名寄せの基本ロジック。

🧮 実値で計算してみる

SSDSE-B-2026 の都道府県名と、 外部公開データの「表記揺れ」を実際に計算してみる。 47 都道府県名はシンプルに見えて、 現場では「東京」「Tokyo」「とうきょう」「TOKYO」「都」省略形など多数の表記が混在する。

SSDSE-B-2026 都道府県コード と 名前の対応

コード正式名表記揺れ例英語表記
R01000北海道北海、 ホッカイドウ、 ほっかいどうHokkaido
R13000東京都東京、 トウキョウ、 とうきょう、 TOKYOTokyo
R14000神奈川県神奈川、 カナガワ、 かながわKanagawa
R27000大阪府大阪、 オオサカ、 おおさか、 OSAKAOsaka
R47000沖縄県沖縄、 オキナワ、 おきなわOkinawa

類似度計算の実例

「東京」と「東京都」の編集距離は 1 (「都」を 1 文字追加)。 Jaccard 係数は文字集合で計算すると {東, 京} と {東, 京, 都}: $J = 2/3 ≈ 0.667$。

「Tokyo」と「TOKYO」は単純比較では別物だが、 大文字化前処理 (str.upper()) を挟むと完全一致 ($d=0$, $J=1$)。

「神奈川県」と「神奈川」の編集距離は 1。 末尾の「都/道/府/県」を除去する前処理 (str.rstrip('都道府県')) で完全一致になる。

よくある表記揺れの 6 パターン

🧮 数式に値を入れて手で計算する: 名寄せの編集距離

合成データで 2 名前のレーベンシュタイン距離を計算する。

Step 1: ペア

name1 = "TANAKA" name2 = "TANAKA-S" (姓ミドル追加) 編集距離: 2 ("-S" 挿入)

Step 2: 類似度

類似度 = 1 - 距離/max(len) = 1 - 2/8 = 0.75 閾値 0.7 以上 → 同一視 (名寄せ可能)

🐍 Python で再現

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def levenshtein(a, b):
    if len(a) < len(b): a, b = b, a
    prev = list(range(len(b)+1))
    for i, ca in enumerate(a, 1):
        cur = [i]
        for j, cb in enumerate(b, 1):
            cur.append(min(cur[-1]+1, prev[j]+1, prev[j-1]+(ca!=cb)))
        prev = cur
    return prev[-1]
n1, n2 = "TANAKA", "TANAKA-S"
d = levenshtein(n1, n2)
sim = 1 - d/max(len(n1), len(n2))
print(f"距離: {d}")
print(f"類似度: {sim:.3f}")

📤 実行結果

距離: 2 類似度: 0.750

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

🐍 Python での実装例

SSDSE-B-2026 などの実データを使った最小コード(6行):

1
2
3
4
5
6
from rapidfuzz import fuzz, process
names = ['株式会社ABC', '(株)ABC', 'ABC Co., Ltd.', 'XYZ商事']
target = '株式会社ABC'
for n in names:
    print(f'{n:20s} 類似度: {fuzz.ratio(target, n)}')
# 高い類似度のものを統合候補に
📤 実行例(実測) 株式会社ABC 類似度: 100.0 (株)ABC 類似度: 61.53846153846154 ABC Co., Ltd. 類似度: 30.000000000000004 XYZ商事 類似度: 0.0

data/raw/SSDSE-B-2026.csve-Stat SSDSE から取得した実データを想定。

🐍 Python 実装

名寄せは「正規化 → 類似度計算 → 閾値判定」の 3 段構成。 SSDSE-B-2026 の都道府県名を題材に段階的に示す。

コード 1: 都道府県名の表記揺れを正規化

🎯 このコードでやること: 「東京」「東京都」「Tokyo」のような表記揺れを共通形に正規化する関数を作る。 SSDSE-B-2026 と JOIN する直前の前処理として使う。

📥 入力例:

names = ['東京', '東京都', 'Tokyo', 'TOKYO', 'とうきょう', '神奈川', '神奈川県']
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def normalize(s):
    s = s.strip().upper()
    s = s.replace('TOKYO', '東京').replace('OSAKA', '大阪')
    s = s.replace('とうきょう', '東京').replace('おおさか', '大阪')
    # 行政区分を除去
    for suffix in ['都', '道', '府', '県']:
        if s.endswith(suffix):
            s = s[:-1]
    return s

names = ['東京', '東京都', 'Tokyo', 'TOKYO', 'とうきょう', '神奈川', '神奈川県']
for n in names:
    print(f'{n}{normalize(n)}')

📤 実行例:

東京 → 東京 東京都 → 東京 Tokyo → 東京 TOKYO → 東京 とうきょう → 東京 神奈川 → 神奈川 神奈川県 → 神奈川

💬 結果の読み方: 7 種の表記が 2 種 (東京 / 神奈川) に集約された。 この共通形をキーに JOIN すれば誤マッチが起きない。

コード 2: difflib で類似度ベース照合

🎯 このコードでやること: SSDSE-B-2026 の都道府県マスタに対し、 表記揺れのある入力を最類似名で復元する。 OCR 誤読補正やユーザー入力の正規化にも使える。

📥 入力例:

user_inputs = ['東京', '神奈川', '大坂', 'Hokkaido', '愛知'] prefs = ['北海道', '青森県', ..., '沖縄県'] # 47 件
1
2
3
4
5
6
7
8
9
import pandas as pd, difflib

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
prefs = df['都道府県'].unique().tolist()

user_inputs = ['東京', '神奈川', '大坂', '愛知']
for u in user_inputs:
    match = difflib.get_close_matches(u, prefs, n=1, cutoff=0.3)
    print(f'{u}{match[0] if match else "(該当なし)"}')

📤 実行例:

東京 → 東京都 神奈川 → 神奈川県 大坂 → 大阪府 愛知 → 愛知県

💬 結果の読み方: 略記や旧字を 80% 以上正しく復元できた。 「大坂 → 大阪府」のような江戸時代の表記揺れも 1 文字違いとして拾える。

コード 3: Levenshtein 距離を自前実装

🎯 このコードでやること: 名寄せの数学的核となる編集距離 (Levenshtein 距離) を DP で実装し、 例題で動作確認する。

📥 入力例:

pairs = [('東京都', '東京者'), ('神奈川', '神奈川県'), ('大阪府', '大坂府')]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def levenshtein(a, b):
    m, n = len(a), len(b)
    dp = [[0]*(n+1) for _ in range(m+1)]
    for i in range(m+1): dp[i][0] = i
    for j in range(n+1): dp[0][j] = j
    for i in range(1, m+1):
        for j in range(1, n+1):
            cost = 0 if a[i-1] == b[j-1] else 1
            dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+cost)
    return dp[m][n]

pairs = [('東京都', '東京者'), ('神奈川', '神奈川県'), ('大阪府', '大坂府')]
for a, b in pairs:
    print(f'{a}{b}: 距離={levenshtein(a, b)}')

📤 実行例:

東京都 ↔ 東京者: 距離=1 神奈川 ↔ 神奈川県: 距離=1 大阪府 ↔ 大坂府: 距離=1

💬 結果の読み方: 3 ペアとも距離 1。 名寄せ閾値を「距離 ≤ 2」に設定すれば、 これらは同一とみなされる。

コード 4: pandas merge で SSDSE-B-2026 と外部データを統合

🎯 このコードでやること: 名寄せ済みのキーで SSDSE-B-2026 と外部 CSV を INNER JOIN する。 正規化関数の効果を体感する。

📥 入力例:

SSDSE-B-2026: 都道府県列 (47 件、 「北海道」「青森県」...) 外部データ: pref 列 (5 件、 「Tokyo」「Osaka」「神奈川」「Hokkaido」「沖縄」)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd

def normalize(s):
    s = s.strip().upper()
    mapping = {'TOKYO':'東京','OSAKA':'大阪','HOKKAIDO':'北海道'}
    for k, v in mapping.items():
        s = s.replace(k, v)
    for suffix in ['都','道','府','県']:
        if s.endswith(suffix): s = s[:-1]
    return s

ssdse = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
ssdse['key'] = ssdse['都道府県'].apply(normalize)

ext = pd.DataFrame({'pref': ['Tokyo', 'Osaka', '神奈川', 'Hokkaido', '沖縄'],
                    '訪問者': [9000, 7000, 5000, 4000, 3000]})
ext['key'] = ext['pref'].apply(normalize)

merged = ssdse.merge(ext, on='key', how='inner')
print(merged[['都道府県', 'pref', '訪問者']])

📤 実行例:

都道府県 pref 訪問者 0 北海道 Hokkaido 4000 1 東京都 Tokyo 9000 2 神奈川県 神奈川 5000 3 大阪府 Osaka 7000 4 沖縄県 沖縄 3000

💬 結果の読み方: 5 種の異なる表記がすべて SSDSE-B-2026 の正式名と結合できた。 名寄せがなければ 0 件マッチで終わっていた。

🐍 追加 Python サンプル

unicodedata で全角半角・かな統一

🎯 このコードでやること: NFKC 正規化で全角→半角、 機種依存文字を ASCII に統一する。 名寄せの大前処理。

📥 入力例:

samples = ['TOKYO', '東京①', 'Ⅰ Ⅱ Ⅲ', '東京​都']
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import unicodedata, re

def deep_normalize(s):
    s = unicodedata.normalize('NFKC', s)
    s = re.sub(r'\s+', '', s)
    s = re.sub(r'[​-‍]', '', s)  # ゼロ幅スペース除去
    return s

samples = ['TOKYO', '東京①', 'Ⅰ Ⅱ Ⅲ', '東京​都']
for s in samples:
    print(f'{s!r}{deep_normalize(s)!r}')

📤 実行例:

'TOKYO' → 'TOKYO' '東京①' → '東京1' 'Ⅰ Ⅱ Ⅲ' → 'IIIIII' '東京​都' → '東京都'

💬 結果の読み方: 全角・丸数字・ローマ数字・不可視文字がすべて正規化された。 名寄せの精度が大きく向上する。

rapidfuzz で高速類似度計算

🎯 このコードでやること: rapidfuzz は C++ 実装の高速文字列類似度ライブラリ。 大規模名寄せでは標準 difflib より 10-100 倍速い。

📥 入力例:

queries = ['東京', '大坂', 'Yokohama'] choices = ['東京都', '大阪府', '横浜市', '名古屋市']
1
2
3
4
5
6
7
8
from rapidfuzz import process, fuzz

queries = ['東京', '大坂', 'Yokohama']
choices = ['東京都', '大阪府', '横浜市', '名古屋市']

for q in queries:
    best = process.extractOne(q, choices, scorer=fuzz.ratio)
    print(f'{q}{best[0]} (スコア {best[1]:.1f})')

📤 実行例:

東京 → 東京都 (スコア 80.0) 大坂 → 大阪府 (スコア 40.0) Yokohama → 横浜市 (スコア 0.0)

💬 結果の読み方: 「東京 → 東京都」は高スコア。 「Yokohama → 横浜市」は文字種が違うためスコア 0。 ローマ字→漢字辞書を併用する必要がある。

Jaro-Winkler 距離で前方一致を強調

🎯 このコードでやること: Jaro-Winkler は文字列の先頭が一致しているとボーナススコアが付く。 人名や住所のように先頭が情報量を持つ文字列に有効。

📥 入力例:

pairs = [('東京都新宿区', '東京都中野区'), ('Tanaka Taro', 'Tanaka Jiro'), ('SSDSE-B-2026', 'SSDSE-A-2026')]
1
2
3
4
5
6
7
8
from rapidfuzz.distance import JaroWinkler

pairs = [('東京都新宿区', '東京都中野区'),
         ('Tanaka Taro', 'Tanaka Jiro'),
         ('SSDSE-B-2026', 'SSDSE-A-2026')]
for a, b in pairs:
    score = JaroWinkler.normalized_similarity(a, b)
    print(f'{a}{b}: 類似度 {score:.3f}')

📤 実行例:

東京都新宿区 ↔ 東京都中野区: 類似度 0.844 Tanaka Taro ↔ Tanaka Jiro: 類似度 0.929 SSDSE-B-2026 ↔ SSDSE-A-2026: 類似度 0.972

💬 結果の読み方: 先頭一致が長いペアほど高スコア。 「SSDSE-B-2026 ↔ SSDSE-A-2026」は 1 文字違いだけだが先頭 5 文字一致で 0.97。

📦 名寄せ用 Python ライブラリ一覧

ライブラリ用途特徴
difflib (標準)小規模名寄せ追加インストール不要、 教育向け
rapidfuzz高速類似度計算C++ 実装、 多数のスコアラ
fuzzywuzzy類似度計算 (旧定番)rapidfuzz への移行推奨
recordlinkageレコードリンケージ全般ブロッキング・分類器内蔵
dedupe能動学習ベース名寄せ対話的にラベル付け
splink確率的リンケージFellegi-Sunter、 大規模対応
jellyfish音素類似度Soundex/Metaphone 等
sentence-transformers埋め込みベース名寄せ多言語 BERT、 意味的類似

🏢 業界別の名寄せ事例

業界名寄せ対象難しさと工夫
医療患者名・薬剤名同姓同名、 略称、 一般名/商品名の対応。 患者 ID 必須。
小売 (CRM)顧客マスタ複数チャネル (店舗・EC・電話) の顧客統合。 メアド・電話番号と住所で判定。
金融企業名・口座名「(株)」「株式会社」「Co., Ltd.」など法人形態の表記揺れ。
学術論文著者名「Yamada T.」「T. Yamada」「山田太郎」を統合。 ORCID で補完。
行政 (e-Stat)市区町村名合併前後の名称、 政令市の区名。 総務省コード履歴と照合。
EC商品マスタ同じ商品が複数 JAN コード。 商品画像・スペック類似度で判定。

⚡ 性能ベンチマーク

「100 万件 × 100 万件」を総当りで比較すると 1 兆ペア。 1 ペア 10μs でも 10^7 秒 ≈ 116 日。 現実的には以下のアプローチで高速化する。

手法100 万件処理時間精度
総当り (difflib)数ヶ月高 (F1 0.95)
総当り (rapidfuzz)数日高 (F1 0.95)
接頭辞ブロッキング数時間中 (F1 0.85)
MinHash + LSH数分中 (F1 0.85)
埋め込み + ANN 検索 (faiss)数分高 (F1 0.93)

SSDSE-B-2026 (47 件) 級なら総当りで瞬時。 e-Stat 全市町村 (約 1700 件) でも数秒。 数百万件超で初めてブロッキング+ANNが必須となる。

⚖️ 名寄せの倫理・法的論点

✅ 名寄せ実装チェックリスト

📝 用語ミニ辞典

用語英語意味
名寄せName Resolution表記揺れを正規化して同一実体を束ねる
エンティティ解決Entity Resolution名寄せの英語圏での主要用語
レコードリンケージRecord Linkage統計学分野での名寄せ呼称
重複排除Deduplication同一実体の重複行を 1 行に集約
ファジーマッチFuzzy Match類似度ベースの曖昧一致
ブロッキングBlocking候補ペアを事前に絞る計算量削減手法
マスタデータMaster Data正規化の参照基準データ
辞書ベースDictionary-based事前定義した対応表で正規化
能動学習Active Learning不確実ペアだけ人にラベル付け依頼
MinHash / LSHLocality Sensitive Hashing類似データを近いハッシュ値に

⚠️ よくある落とし穴

❌ 正規化漏れ
全角/半角、 大小、 法人格表記の揺れ — 事前に統一を。
❌ 過剰統合
「鈴木一郎」と「鈴木一朗」を同一視 → 誤統合のリスク。
❌ 計算量爆発
n=10万の全比較は1兆ペア。 ブロッキングで絞る。
❌ 黒箱化
ML名寄せの判定根拠を残さないと監査できない。

⚠️ 落とし穴

🗺 学習ロードマップ

  1. (1 週目) 正規化の基礎 — Python str / unicodedata / re で「TOKYO → 東京都」のような前処理を自分で書けるようになる。
  2. (2 週目) 類似度関数を実装 — Levenshtein / Jaccard / Cosine を自前で書き、 動作を体感する。
  3. (3 週目) ライブラリ活用 — rapidfuzz / recordlinkage で SSDSE-B-2026 と外部データを結合する小演習。
  4. (4 週目) ブロッキング — 数十万件規模を扱い、 接頭辞ブロッキング・MinHash の効果を実験。
  5. (5 週目) 機械学習ベース — dedupe や splink で確率モデル・能動学習を体験。
  6. (6 週目) 統合演習 — 自分で集めた外部データ (オープンデータ・スクレイピング結果) を SSDSE-B-2026 と結合し、 オリジナル分析を組む。

📖 参考リソース

名寄せ Entity Resolution 文字列正規化 ブロッキング 類似度計算 重複排除 レコードリンケージ 正規化辞書

🔗 隣接手法への橋渡し

「名寄せ」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。

名寄せは前処理の要であり、 ここで束ね損ねた表記揺れは下流の集計・相関・回帰・可視化のすべてに伝播する。 「正規化 → ブロッキング → 類似度計算 → 閾値/クラスタリング判定」の各段を、 上流のクレンジングと下流の分析をつなぐパイプラインとして設計するのが実務上の論点になる。

🌳 手法選択フロー

名寄せ手法の選択は「規模・精度・運用コスト」のトレードオフ。

  1. 小規模・表記揺れが軽微 (SSDSE-B-2026 の 47 都道府県など) → NFKC 正規化 + 置換辞書による完全一致で十分
  2. 中規模・揺れが多い → Jaro-Winkler / rapidfuzz によるファジーマッチ + 閾値判定
  3. 大規模 (数百万件以上) → 接頭辞ブロッキング / MinHash で候補を絞り、 確率的リンケージ (Fellegi-Sunter) や機械学習 (dedupe・splink) を併用

迷ったら「まずルールベース (正規化 + 辞書) で限界まで精度を上げ、 それでも足りなければ機械学習」が鉄則。 どの規模でも最後は merge(indicator=True) と可視化で突合結果を検証すること。

🧪 解説の深化:名寄せを「検算」する — 件数保存則と静かな欠落

ここまでのセクションは「どう束ねるか」(正規化・類似度・閾値)を扱ってきました。 この節は視点を変えて、 束ねた後にどう品質を保証するか — つまり名寄せの監査・検算を扱います。 名寄せの失敗は例外を投げません。 結合の後に件数を数えることでしか発見できないのです。

💡 直感 — 名寄せの合否は「結合後の件数保存則」で判定する

47 都道府県のデータ同士を結合するなら、 名寄せが完璧である条件はただ 1 つ、 merge(..., how='outer', indicator=True)_merge 列が both = 47、 left_only = 0、 right_only = 0 になること。 これを本節では件数保存則と呼びます。 物理の保存則と同じで、 「合計が合わない=どこかで漏れている」ことの確実なシグナルです。

表記揺れがどれほど致命的かは SSDSE-B-2026 で実測できます。 Prefecture 列(2023 年、 47 件)の末尾は 「県」43・「都」1・「府」2・「道」1。 もし外部データが「東京」「大阪」「青森」のように末尾の 都・府・県 を落とした表記だったら、 完全一致で結合できるのは末尾を削っても変わらない「北海道」のたった 1 件(47 件中 1 件)。 残り 46 件は音もなく消えます。

⚠️ 落とし穴(重要) — inner join の「静かな欠落」は集計を黙って歪める

how='inner'(pandas の既定値)は、 キーが一致しなかった行をエラーなしで捨てます。 SSDSE-B-2026 の 2023 年・総人口(A1101)の実測値で影響を見ると:

実務のチェックリスト: (1) 結合は一度 how='outer', indicator=True で行い left_only / right_only の中身を必ず表示する、 (2) assert len(merged) == 47 のように期待件数を明示する、 (3) 結合キーの nunique() を両テーブルで比較する、 (4) 落ちた行は「静かに」ではなくログに残して捨てる。 落ちた行が欠損値 (NaN) として現れる left join 側の扱いは 欠損値 も参照。

🚀 発展 — 「名前で結合しない」というキー設計

最も強い名寄せ対策は、 文字列をキーにしないことです。 SSDSE-B-2026 には Code 列(R01000〜R47000、 JIS X 0401 都道府県コードに基づく 47 個の一意キー)があり、 コード付きの外部統計とはこれで結合すれば表記揺れ問題そのものが消滅します。 コードが無い外部データに対しては、 「① 名寄せしてコードを付与する(ここだけ人手検証) → ② 以降の結合はすべてコードで行う」という二段構えにすると、 名寄せコストを 1 回に封じ込められます。

さらに先へ進むなら: Fellegi-Sunter 型の確率的リンケージを実装した splink(数千万件規模対応)、 文字距離では拾えない同義表記を埋め込みベクトルで束ねる埋め込みベース Entity Matchingコサイン類似度で候補生成)、 そして「どの規則・どのスコアで統合したか」を後から遡れる判定来歴(provenance)の保存。 名寄せの正解率評価は 2 値判定なので、 混同行列適合率と再現率F1 スコア の枠組みがそのまま使えます。

※ 本節の数値はすべて SSDSE-B-2026(2023 年・47 都道府県、 総人口 A1101・Prefecture・Code 列)からの実測値です。