郵便番号から緯度経度を計算
JPからは郵便番号一覧が配布されており、国土交通省からは住所と緯度経度一覧が配布されている。これを合わせて、郵便番号から緯度経度を引けるようにした。国土交通省のデータ方が多いので、マッチングして出た点の緯度経度の平均をとる。
JPのデータを読む関数はこんな感じだ。
def read_zip(file_name):
# read zipcode data
name =["code","zip5","zip7","yomi1","yomi2","yomi3","name1","name2","name3","other1","other2","other3","other4","other5","reason"]
zipcode = pd.read_csv(file_name, names=name, encoding='cp932')
zipcode = zipcode[ ["zip7","yomi3","name1","name2","name3"] ]
# extract section
pat1 = r"(.+)$"
pattern1 = re.compile(pat1)
zipcode["大字"] = zipcode["name3"].replace(pattern1, '', regex=True)
# Extract section number
pat1 = r"(\d+-\d+チヨウメ)"
pattern1 = re.compile(pat1)
zipcode["丁目"] = zipcode["yomi3"].str.extract(pattern1)
return zipcode
Pandasで読んだ後に正規表現で大字と丁目データを追加している。
国土交通省のデータは以下の関数で読む。
def read_df(file_name):
df = pd.read_csv(file_name, encoding='cp932')
# Remove the section number
pat2 = r"[一二三四五六七八九十壱弐参拾百千万萬億兆〇]+丁目$"
pattern2 = re.compile(pat2)
df["大字"] = df["大字町丁目名"].replace(pattern2, '', regex=True)
#丁目の番号は大字町丁目コードの下3桁
df["丁目"] = df["大字町丁目コード"] % 100
return df
これも正規表現で大字を抽出し、丁目番号をコードから生成しただけだ。
2つのデータをマッチングさせて緯度経度を計算し、郵便番号のデータフレームに保管する。
def compute_lat_lng(zipcode,df):
# Compute the latitude and longitude for each zipcode using the government database (named df)
count =0
lat_column, lng_column = [ ],[ ]
for row in zipcode.itertuples():
try:
cyoume = row.丁目.split("-")
#print(cyoume)
start, finish = int(cyoume[0]), int(cyoume[1][:-4]) #start cyoume and finish cyoume
except:
start, finish = 0, 0
extract = df[ (df["都道府県名"] == row.name1) & (df["市区町村名"]==row.name2) & (df["大字"]==row.大字)]
if len(extract)==0:
extract = df[ (df["都道府県名"] == row.name1) & (df["市区町村名"]==row.name2) & (df["大字"]=="大字"+row.大字)]
#print( count, len(extract), start, finish )
lat_list, lng_list = [ ],[ ]
if len(extract)>0: #compute the median point
for row2 in extract.itertuples():
if start<finish: #cyoume has a range
if start<=row2.丁目 and row2.丁目 <=finish:
lat_list.append(row2.緯度)
lng_list.append(row2.経度)
else:
lat_list.append(row2.緯度)
lng_list.append(row2.経度)
lat_column.append( sum(lat_list)/len(lat_list) )
lng_column.append( sum(lng_list)/len(lng_list) )
else:
#no coreesponding row in df
lat_column.append(0.)
lng_column.append(0.)
count+=1
zipcode["latitude"] = pd.Series(lat_column)
zipcode["longitude"] = pd.Series(lng_column)
return zipcode
あとは47都道府県のファイル名を入れて回すだけだ。10分くらい回すと出来上がりだ。pickleでzip圧縮で保存すればいつでも使える。数万円で販売している会社もあるようだが、買う人がいるのだろうか?
追記:と思ったら無料で配布している人を見つけた。「時間をかけて」と書いてあったので、上限つきのAPIサービスなどでコツコツ変換したのかもしれない。とは言っても郵便番号の精度はいまいちなので、国土交通省の細かい方のデータを使ってジオコーディングするAPIを作った方が実用的だろう。MapBoxもゼンリンと提携したようなので、使えるようになれば描画と一緒に使った方が早いかもしれない。
この記事が気に入ったらサポートをしてみませんか?