1. はじめに

住所データは、企業の顧客管理システムや配送システムなど、さまざまなシステムで利用されます。しかし、入力データの形式がバラバラだと、データがうまく突合されなかったり、システムの不具合、障害の原因になることがあります。特に、画面からの入力時のチェックが不十分なシステムでは起こりがちです。

本記事では、全角・半角の違いや表記の揺れによりばらつく住所データを、都道府県、市区町村、番地といった各項目に分割し、統一フォーマットに変換する方法について、Pythonを使った実装例を交えながら解説します。1/2では、文字列から都道府県、市、番地を切り分けるところまでやります。

2. 住所データの現状と課題

全角・半角の不統一

日本語の住所データでは、数字や記号が全角と半角で混在するケースが多く見られます。例えば、
・「東京都新宿区」
・「新宿区, 東京」
といった入力がある場合、全角の「、」や半角の「,」が混在しているため、単純な文字列比較では同一と認識されにくいです。

表記の揺れの実例

住所の表記方法には個人差があり、以下のような表記の揺れが発生します。
・都道府県名の省略(例:「東京」 vs 「東京都」)
・市区町村名の前後に不要な空白や記号が入る
・番地の記載方法に違いがある(例:「1-2-3」 vs 「1−2−3」)
このような表記の不一致は、データ検索や集計、システム間のデータ連携の際に大きな障害となります。正規化することで、データ品質が向上し、システムの信頼性を高めることができます。

3. 正規化の基本概念と用語解説

用語解説

  • 都道府県: 日本の行政区分の最上位に位置する地域(例:東京都、大阪府など)。
  • 市区町村: 都道府県の下位に位置する自治体(例:新宿区、横浜市など)。
  • 番地: 市区町村以下の細かい住所情報。建物番号や丁目を含む情報です。

正規化と統一フォーマットの定義

「正規化」とは、ばらばらな入力データを一定のルールに従って整理・統一する処理を指します。
統一フォーマットとしては、例えば「都道府県 市区町村 番地」という形に整形することが考えられます。これにより、システム全体で一貫性のあるデータが利用できるようになります。

4. Pythonで住所データを正規化する手法

Pythonには文字列処理に便利なライブラリが多数存在します。

正規表現(reモジュール)

住所データから特定のパターンを抽出するために、Pythonのreモジュールを使用するのが一般的です。
例えば、全角と半角の数字・記号を統一したり、不要な空白や記号を削除する処理を実装できます。

pandasによるデータ処理

大量の住所データがある場合、pandasを利用してDataFrame内の各レコードに対して正規化処理を実施するのが効率的です。
pandasのapplyメソッドなどを活用すれば、データ全体に対する一括処理が容易になります。

5. 実践!住所データ正規化のコード例

ここでは、具体的なコード例を紹介します。以下のサンプルコードでは、入力された住所文字列から都道府県、市区町村、番地を抽出し、統一フォーマットに変換する基本的な処理を実装しています。

import re

def normalize_address(address):
    # 全角数字・記号を半角に変換(必要に応じて実装。ここでは例示のみ)
    # 例:全角カンマ「,」を半角カンマ「,」に変換
    address = address.replace(',', ',')
    
    # 不要な空白を削除
    address = re.sub(r'\s+', ' ', address).strip()

    # 例として、都道府県と市区町村を抽出する正規表現(実際のパターンは調整が必要)
    pattern = r'(東京都|京都府|大阪府|.+?県)?\s*(.+?[市区町村])\s*(.*)'
    match = re.match(pattern, address)
    
    if match:
        prefecture = match.group(1) if match.group(1) else ''
        city = match.group(2) if match.group(2) else ''
        rest = match.group(3) if match.group(3) else ''
        # 番地部分の不要な記号を削除(例:カンマ)
        rest = rest.replace(',', '')
        # 統一フォーマット: 「都道府県 市区町村 番地」
        normalized = f"{prefecture} {city} {rest}".strip()
        return normalized
    else:
        return address

# サンプル入力と出力例
addresses = [
    "東京都新宿区",
    "新宿区, 東京",
    "大阪府 大阪市, 1-2-3",
    "北海道札幌市 1−2−3"
]

for addr in addresses:
    print(f"入力: {addr} -> 出力: {normalize_address(addr)}")
  

サンプル出力

入力: 東京都新宿区 -> 出力: 東京都 新宿区 
入力: 新宿区, 東京 -> 出力:  東京 新宿区
入力: 大阪府 大阪市, 1-2-3 -> 出力: 大阪府 大阪市 1-2-3
入力: 北海道札幌市 1−2−3 -> 出力: 北海道 札幌市 1−2−3
  

※上記コードはあくまで基本的な例です。実際のデータや要件に合わせて正規表現や変換ルールを調整する必要があります。

6. 応用編:異なるフォーマットのデータ処理

多様なデータ形式への対応方法

住所データは入力パターンが多岐にわたるため、以下のような対応が考えられます。

  • 前処理の強化
    入力データのパターンを洗い出し、全角・半角変換、不要な記号の削除、余分な空白の除去などの前処理を追加する。
  • 複数の正規表現パターンを用意
    都道府県や市区町村の抽出に失敗した場合、別のパターンで再度抽出を試みるなど、条件分岐を設ける。

エラー処理と例外ケースの取り扱い

  • 抽出に失敗した場合のデフォルト処理
    正規表現でマッチしなかった場合は、ログに記録するか、もしくはそのままの文字列を返すなどの対応を検討する。
  • データ不備への対応
    異常値や欠損値に対しては、pandasのfillnadropnaメソッドを活用して前処理段階で対処する。

7. まとめ

本記事では、文字列から都道府県、市、番地を切り分けるところまで紹介しました。

2/2では、簡単なマスタを使って、表現を統一し、また全角、半角を統一する方法を紹介します。

続きの記事は以下となります。

[Python]住所データの正規化(2/2) | 業務で使うPython前処理