moon-fondu様
こんにちは。
私はプログラマなので、市区町村データとマッチして取得しています。
例)総務省のサイトでEXCELで用意されています。
http://www.soumu.go.jp/denshijiti/code.html
例)Yahooではプログラムが作れる人ならWEB APIで用意されています。
http://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/addressdirectory.html
【注意事項】
・「ケ」と「ヶ」の違いもあるかも知れません。
・漢字の違いに注意が必要かも知れません。
龍ケ崎市、竜ヶ崎市 等々
・市区町村をどこまで取得するかも検討が必要です。
札幌市 までか?
札幌市中央区 までか?
・市区町村合併により町名変更も注意する必要があります。
以上、ご検討ください。
▽2
●
a-kuma3 ●3000ポイント ベストアンサー |
以下のコードを標準モジュールに貼り付けて、extract_city サブルーチンを実行してください。
A列の住所から市区町村郡を切り出して、B列にセットします。
Sub extract_city() source_col = 1 ' A列 : 住所 dest_col = 2 ' B列 : 市区町村 last_row = Cells(Rows.Count, source_col).End(xlUp).Row Set re_z = CreateObject("VBScript.RegExp") Dim re_c(7) For i = 0 To 7 Set re_c(i) = CreateObject("VBScript.RegExp") Next re_z.Pattern = "^(.{2}[都道府]|.{2,3}[県])(.+)" re_c(0).Pattern = "^(郡山市|市川市|市原市|郡上市|蒲郡市|四日市市|大和郡山市|廿日市市|小郡市|野々市市|高市郡|余市郡)" re_c(1).Pattern = "^([^郡]+郡)" re_c(2).Pattern = "^([^市]+市)" re_c(3).Pattern = "^([^区]+区)" re_c(4).Pattern = "^([^町]+町)" re_c(5).Pattern = "^([^村]+村)" re_c(6).Pattern = "^([^区]+区)" ' 東京都用 re_c(7).Pattern = "^([^市]+市)" ' 東京都用 For r = 2 To last_row s = Cells(r, source_col).Value Set mat = re_z.Execute(s) If mat.Count = 0 Then Cells(r, dest_col).Value = "都道府県が見つかりません" GoTo Continue End If Z = mat(0).SubMatches(0) s = mat(0).SubMatches(1) i_begin = 0 i_end = 5 If Z = "東京都" Then i_begin = 6 i_end = 7 End If For i = i_begin To i_end Set mat = re_c(i).Execute(s) If mat.Count > 0 Then If i <> 1 Then Cells(r, dest_col).Value = mat(0).SubMatches(0) Else ' 「郡」だけ特別扱い Set mat2 = re_c(2).Execute(s) ' 「市」を含む? If mat2.Count > 0 Then '短い方を採択 If Len(mat(0).SubMatches(0)) > Len(mat2(0).SubMatches(0)) Then Cells(r, dest_col).Value = mat2(0).SubMatches(0) Else Cells(r, dest_col).Value = mat(0).SubMatches(0) End If Else Cells(r, dest_col).Value = mat(0).SubMatches(0) End If End If GoTo Continue End If ' DoEvents Next Continue: Next End Sub
五万件だと数分かかると思います。
その間にもシートを操作したいのであれば、末尾の方でコメントにしてある DoEvents を活かしてください。
コメントを外すと、完了までの時間は更に長くなりますが、処理中にもシートの操作ができます。
処理内容の説明をしておきます。
「郡→市→区→町→村」の順番で検索すると、エラーの発生を最小にすることができます
上記のロジックを参考にしました。
ただ、「郡」や「市」を市の名前に含む9件を例外扱いにしただけでは、以下のような住所が適切に扱えません。
山形県南陽市郡山
大阪府交野市郡津
山口県山口市小郡
鹿児島県鹿児島市郡元町
そこらあたりを、実際の住所データ(何かの回答の折に使った 9000件くらいの全国の)を使いながらロジックを調整しました。
「郡」が見つかった場合には、「市」でも探してみて、短い方を採用しています。
それでも、「奈良県高市郡」、「北海道余市郡」は正しく抽出できないので、特別扱いにしています。
対象の住所によっては、正しく処理できないものがあると思います。
コメントで紹介されている総務省の「全国地方公共団体コード」から表引きにすることもちらっと考えましたが、
と思って止めました。
後、質問では「郡」を切り出しの対象にしているのでそのような処理にしていますが、「郡」で切ってしまうと、「町」や「村」が抽出されないと思います。
入力済みの住所データ次第ですが、「○○郡△△村」のような表記になっているはずなので。
#「郡」も例外的なのがもっとあるんだろうなあ...
「郡の変遷」に 2014年4月1日時点での「郡」の情報がまとめられていて、「郡」の名称に「市」が入るのは、「余市」と「高市」だけっぽいことは確認しました。
「町」、「村」の切り取りは、まとめて先頭一致の表引きでも良いでしょう(遅いけど)。
表引きでも、素直に表と照らし合わせるだけでは駄目でヒューリスティックなロジックにならざるを得なし、市区町村のリストは頻繁ではないにしても更新が入りますので使い続けるつもりのプログラムなら保守が必要。
だったら表なんか使わなくても良いかなあ、という印象です。
の完全なリストが手に入る。
全部で 1894件。
これを長い順に並べ替えて、住所から都道府県を切り取った文字列と先頭一致で比較して一致したら採用。
「郡は要らない」とか「郡の方を採用」は、一覧にある文字列を加工する感じでしょうか。
ロジックは単純になりますね。
# 総務省の「全国地方公共団体コード」の方は 1741 件で、150件ほど差があるのは廃止になったものを一部含んでいるからかな?
# 総務省の「全国地方公共団体コード」の方は 1741 件で、150件ほど差があるのは廃止になったものを一部含んでいるからかな?
いや、郵便番号の方は「○○市○○区」の表記だからだった。
一部の差異を除いて、ほぼ同じ。
漢字の表記の違いが2件と、「郡」ではなく「島」という表記が 2件(三宅島と八丈島)。
東京都だからだなあ、きっと。
良くも悪くも入手できる一覧は最新なので、市区町村を切り出す対象の住所に古いものが含まれると、取りこぼしがありそうです。
ぼくが試したデータでは 2.8% を取りこぼしているので、プログラムで切り出した方が例外が少ないという結果になります。
一覧表のデータは、プログラムで切り出した値の検算に使うのが良いかな、という気がしました。
形態素解析を使ってみてはどうでしょう。
http://tech.gmodecorp.com/post/121092256636/mecab
EXCELから使えるものもあるようですがいずれにしろVBAなどscriptが必要になると思います。
形態素解析器はいくつかあるようですがmecabで試してみました。
サンプルとして
東京都港区芝公園4丁目2?8
福島県安達郡大玉村玉井字長久保68
岐阜県山県市大森
山形県南陽市郡山
大阪府交野市郡津
山口県山口市小郡
鹿児島県鹿児島市郡元町
奈良県高市郡
北海道余市郡
をmecabの分かち書きすると
東京 都 港 区 芝公園 4 丁目 2 ? 8
福島 県 安達 郡 大玉 村 玉井 字 長久保 6 8
岐阜 県 山県 市 大森
山形 県 南陽 市 郡山
大阪 府 交野 市 郡津
山口 県 山口 市 小郡
鹿児島 県 鹿児島 市 郡元 町
奈良 県 高市 郡
北海道 余市 郡
のようになります。
感じとしては空白で区切られた三番目と四番目のものを使えば
市区町村名(区名)のみを抽出することができます。
しかし北海道は北海 道ではないので例外になり面倒なので
やはりscriptを使います。コードが短くてすむrubyで書きました。
require 'natto'
natto = Natto::MeCab.new
while text = ARGF.gets
na = natto.enum_parse(text).map {|n| n}
of = na[1].feature.split(',')[1] == '接尾' ? 2 : 1
puts "#{na[of].surface}#{na[of+1].surface}"
end
実行結果は
港区
安達郡
山県市
南陽市
交野市
山口市
鹿児島市
高市郡
余市郡
となります。例外があると思いますがrubyスクリプトで対応することになるので苦手だと厳しいかもしれません。
mecabは辞書を使って処理しているので希望するものに近い結果を受け取ることができると思います。