「住所データを整形する」の版間の差分

提供: dococo wiki
ナビゲーションに移動 検索に移動
imported>Webmaster
imported>Webmaster
 
5行目: 5行目:
  
 
== 住所合わせ ==
 
== 住所合わせ ==
よく問題になるのが住所の不整合。典型的な例では以下のような場合<br />
+
名寄せ(ここでは、住所合わせ)の典型的な例として以下のような場合がある<br />
 
#<code>福島県郡山市田村町桜ケ丘1丁目</code>
 
#<code>福島県郡山市田村町桜ケ丘1丁目</code>
 
#<code>福島県郡山市田村町桜ケ丘一丁目</code>
 
#<code>福島県郡山市田村町桜ケ丘一丁目</code>
両方とも意味は合っているので間違っていないけど、EXCELなどのVLOOKUPで引っかけようとすると半角と全角、アラビア数字と漢数字が混ざっているためそう簡単には比較できないようになっている。<br />
+
両方とも人間の目には合っているので間違っていないけど、EXCELなどのVLOOKUPで引っかけようとすると半角と全角、アラビア数字と漢数字が混ざっているためそう簡単には比較できないようになっている。<br />
 
日本語の住所表記の性(サガ)というか仕方ないけど、これを綺麗に整形(あるルールに則って文字を変更させる)方法についてPerlを使って説明する<br />
 
日本語の住所表記の性(サガ)というか仕方ないけど、これを綺麗に整形(あるルールに則って文字を変更させる)方法についてPerlを使って説明する<br />
 +
 
== 異なる住所情報 ==
 
== 異なる住所情報 ==
 
2つの住所が異なるポイントは以下の条件があると考える<br />
 
2つの住所が異なるポイントは以下の条件があると考える<br />

2017年3月4日 (土) 08:37時点における最新版

はじめに

地図を加工するときに2種類の住所データを比較してプロットしたいことがよくある
例えば、丁町目ポリゴンデータとデータを測定した際の住所を重ね合わせる場合、世間的には11桁コードというデータ(要するに住所を数字化した物)で突合させるらしい。しかし、費用がかかるので出来るだけ安く突合できないか考えてみた
この手の作業を「名寄せ」とか「類似データの絞り込み」とか「住所正規化」とか「データクレンジング(データクリーニング/名寄せ)」とか言います

住所合わせ

名寄せ(ここでは、住所合わせ)の典型的な例として以下のような場合がある

  1. 福島県郡山市田村町桜ケ丘1丁目
  2. 福島県郡山市田村町桜ケ丘一丁目

両方とも人間の目には合っているので間違っていないけど、EXCELなどのVLOOKUPで引っかけようとすると半角と全角、アラビア数字と漢数字が混ざっているためそう簡単には比較できないようになっている。
日本語の住所表記の性(サガ)というか仕方ないけど、これを綺麗に整形(あるルールに則って文字を変更させる)方法についてPerlを使って説明する

異なる住所情報

2つの住所が異なるポイントは以下の条件があると考える

  1. 「ケ」か「ヶ」か「が」か(例:百合ヶ丘/百合が丘)
  2. 「ツ」か「ツ」か
  3. 「ノ」か「ノ」か「の」か「乃」か「之」か
  4. 「12丁目」か「12丁目」か「十二丁目」か「一二丁目」か
  5. 「通り」か「通」か

といろいろありますが、使いながら合わせていくしか有りませんね

サンプルプログラム

ここではまず

  • 半角を全角にする
  • アラビア数字を漢数字にする

というルールの変換を行いたいと思います

#UTF-8で保存する
use strict;
use warnings;
use utf8;
use Encode;#これがないと「Undefined subroutine &main::encode called at」が出る
use Unicode::Japanese;

#$str_hに半角データを入れる
my $str_h = '福島県郡山市田村町桜ケ丘123丁目';

#Unicode::Japaneseで表示してみるcp932でもsjisでも表示される
print Unicode::Japanese->new($str_h)->cp932,"\n";


#数字を漢数字に変換
  # 数字は半角にそろえておく
    $str_h =~ y/1234567890/1234567890/;
  # 単独の0は「ゼロ」に書き換える
    $str_h =~ s/(?<!\d)0(?!\d)/ゼロ/g; 
  # 桁区切りのコンマを取っておく
    $str_h =~ s/(?<=\d),(?=(\d\d\d)+(?!\d))//g;
  # 4桁ごとに区切って万億兆を挿入
    $str_h =~ s/(?<=\d)(?=\d\d\d\d(?!\d))/万/g;
    $str_h =~ s/(?<=\d)(?=\d\d\d\d(?=万))/億/g;
    $str_h =~ s/(?<=\d)(?=\d\d\d\d(?=億))/兆/g;
  # 下から1桁ずつ十百千を挿入
    $str_h =~ s/(?<=\d)(?=\d(?!\d))/十/g;
    $str_h =~ s/(?<=\d)(?=\d(?!\d))/百/g;
    $str_h =~ s/(?<=\d)(?=\d(?!\d))/千/g;
  # 0になってる桁を削除
    $str_h =~ s/0[十百千]//g;
    $str_h =~ s/億0万/億/g;
    $str_h =~ s/兆0億/兆/g;
    $str_h =~ s/0//g;
  # 十百には1をつけない
    $str_h =~ s/1([十百])/$1/g;
  # 各桁を漢数字に書き換え
    $str_h =~ y/123456789/一二三四五六七八九/;

#h2z(半角から全角)->cp932を->getとするとutf8で保存される
print Unicode::Japanese->new($str_h)->h2z->cp932,"\n";

これを実行した場合以下の結果になります
福島県郡山市田村町桜ケ丘123丁目
福島県郡山市田村町桜ケ丘百二十三丁目
まずは、これでVLOOKUPあわせを行いたいと思います。