日本の自治体における「○○町」が「ちょう」と読むか「まち」と読むかに関する記事を見かけました。
“町”は「まち」か「ちょう」か…調査して分かった東日本・西日本での傾向 境界線らしき川が長野にあった(最終閲覧日:2021年8月6日)

長野あたりに境界ができるのは面白いですね。
私はこの記事を読んで、駅名でも「ちょう」と読むか「まち」と読むかの境界線があるかどうか気になりました。そこで、データの取得(スクレイピング)、簡単なデータ分析、foliumによる位置情報の図示化をしてみました。
データ取得
データは以下のWikipediaのリンクから出発して、BeautifulSoupでスクレイピングしました。 日本の鉄道駅一覧 - Wikipedia今回取得および作成したデータは以下の通りです:
- 名称に「町」のつく駅の駅名(先頭が町の駅も含む)
- 駅名の仮名
- 「ちょう」か「まち」かを判別するラベル
- 都道府県
- 緯度
- 経度
from bs4 import BeautifulSoup
import requests
import re
import time
url = "https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E3%81%AE%E9%89%84%E9%81%93%E9%A7%85%E4%B8%80%E8%A6%A7"
res = requests.get(url)
soup = BeautifulSoup(res.content,'html.parser')
# 50音のリンクを取得
list_url_aiueo = ["https://ja.wikipedia.org"+x.get("href") for x in soup.select('td>a') if "日本の鉄道駅一覧" in x.get("title")]
list_url_all = []
list_name_all = []
list_namekana_all = []
# 50音のリンクから駅名に「町」を含む駅を取得
for url in list_url_aiueo:
print(url)
res = requests.get(url)
soup = BeautifulSoup(res.content,'html.parser')
list_name = [x.text for x in soup.select('li>a') if "町" in re.sub(r"\(.+?\)$", "", x.text)]
list_namekana = [x.parent.text.replace(x.text, "")[1:-1] for x in soup.select('li>a') if "町" in re.sub(r"\(.+?\)$", "", x.text)]
list_url = ["https://ja.wikipedia.org"+x.get("href") for x in soup.select('li>a') if "町" in re.sub(r"\(.+?\)$", "", x.text)]
list_name_all.extend(list_name)
list_namekana_all.extend(list_namekana)
list_url_all.extend(list_url)
#2秒待つ
time.sleep(2)
data = []
for n in range(len(list_url_all)):
d = []
name = list_name_all[n]
print(name)
name_kana = list_namekana_all[n]
url = list_url_all[n]
print(url)
res = requests.get(url)
soup = BeautifulSoup(res.content,'html.parser')
#文字列 name_kana 内に…
#"ちょう"も"まち"も含む → 0
#"ちょう"を含むが、"まち"は含まない → 1
#"ちょう"を含まないが、"まち"は含む → 2
#"ちょう"も"まち"も含まない(そんな駅はなさそうだが一応)→3
if "ちょう" in name_kana:
if "まち" in name_kana:
tyou_machi = 0
else:
tyou_machi = 1
else:
if "まち" in name_kana:
tyou_machi = 2
else:
tyou_machi = 3
#wikiの本文は「○○駅は、××県にある△△線の駅である」で始まることが予想される
#→pタグ内の最初のaタグを取得すれば都道府県が取得できそう(あとで要検証)
#「○○停留場」とあるのにリンク先は「○○駅」になっていたものもあったので、文字列一致条件から除外
nm = re.sub(r"\(.+?\)$", "", name).strip().replace("停留場","")
if [x.text for x in soup.select('p>a') if x.parent.text[:len(nm)]==nm] == []:
pref = None
else:
pref = [x.text for x in soup.select('p>a') if x.parent.text[:len(nm)]==nm][0]
time.sleep(2)
list_href = [x.get("href") for x in soup.select("a") if x.get("href") != None]
if [x for x in list_href if "geohack" in x] == []:
latitude = None
longitude = None
else:
url_map = [x for x in list_href if "geohack" in x][0]
print(url_map)
res_map = requests.get(url_map)
soup_map = BeautifulSoup(res_map.content,'html.parser')
latitude = soup_map.select_one('span[class^="latitude p-latitude"]').text
longitude = soup_map.select_one('span[class^="longitude p-longitude"]').text
d = [name, name_kana, tyou_machi, pref, latitude, longitude]
data.append(d)
time.sleep(2)
print("end")
上記で取得したcsvをpandasで読み込み、正しく取得できていない都道府県データを確認します。
import pandas as pd
df = pd.DataFrame(data, columns=["駅名", "かな", "ちょう1まち2", "都道府県", "緯度", "経度"])
# 緯度経度をfloat型にする
df["緯度"].astype(float)
df["経度"].astype(float)
pref_list = ["北海道","青森県","岩手県","宮城県","秋田県"
,"山形県","福島県","茨城県","栃木県","群馬県"
,"埼玉県","千葉県","東京都","神奈川県","新潟県"
,"富山県","石川県","福井県","山梨県","長野県"
,"岐阜県","静岡県","愛知県","三重県","滋賀県"
,"京都府","大阪府","兵庫県","奈良県","和歌山県"
,"鳥取県","島根県","岡山県","広島県","山口県"
,"徳島県","香川県","愛媛県","高知県","福岡県"
,"佐賀県","長崎県","熊本県","大分県","宮崎県"
,"鹿児島県","沖縄県"]
# pref_listに載ってないデータを見る
df.query(f"都道府県 not in {pref_list}")
駅名 かな ちょう1まち2 都道府県 緯度 経度
41 恵美須町駅 えびすちょうえき・Osaka Metro堺筋線 1 阪堺電気軌道 34.653867 135.504878
42 恵美須町停留場 えびすちょうていりゅうじょう・阪堺電気軌道阪堺線 1 阪堺電気軌道 34.653867 135.504878
44 猿猴橋町停留場 えんこうばしちょうていりゅうじょう 1 広島市 34.394794 132.476033
96 紙屋町西停留場 かみやちょうにしていりゅうじょう 1 None 34.39525 132.457667
97 紙屋町東停留場 かみやちょうひがしていりゅうじょう 1 None 34.39525 132.457667
108 観音町停留場 かんおんまちていりゅうじょう・広島電鉄本線 2 広島市 34.395503 132.438578
123 小網町停留場 こあみちょうていりゅうじょう 1 広島市 34.394456 132.44435
151 桜木町駅 (YOKOHAMA AIR CABIN) さくらぎちょうえき・泉陽興業YOKOHAMA AIR CABIN 1 None 35.451389 139.631472
192 陣屋町臨港駅 じんやまちりんこうえき 2 None 42.367875 140.949989
244 伝馬町駅 てんまちょうえき・名古屋市営地下鉄名城線 0 名古屋市 35.120833 136.910556
245 天満町停留場 てんまちょうていりゅうじょう・広島電鉄本線 0 広島市 34.3951 132.440878
246 十日市町停留場 とうかいちまちていりゅうじょう 2 広島市 34.39735 132.44765
266 西観音町停留場 にしかんおんまちていりゅうじょう 2 広島市 34.394061 132.436672
287 浜町アーケード停留場 はまのまちアーケードていりゅうじょう 2 None 32.743764 129.876081
303 福島町停留場 ふくしまちょうていりゅうじょう 0 広島市 34.394875 132.433975
305 袋町停留場 ふくろまちていりゅうじょう 2 広島市 34.391183 132.456211
313 舟入川口町停留場 ふないりかわぐちちょうていりゅうじょう 1 広島市 34.380453 132.439639
315 舟入本町停留場 ふないりほんまちていりゅうじょう 2 広島市 34.385714 132.442714
316 舟入町停留場 ふないりまちていりゅうじょう 2 広島市 34.389403 132.444978
326 本川町停留場 ほんかわちょうていりゅうじょう 1 広島市 34.396839 132.450483
328 本町一丁目停留場 ほんまちいっちょうめていりゅうじょう 0 None 33.840139 132.758339
336 町屋駅前停留場 まちやえきまえていりゅうじょう 2 None 35.742222 139.781389
360 皆実町六丁目停留場 みなみまちろくちょうめていりゅうじょう 0 広島市 34.3742 132.464058
370 モノレール浜松町駅 モノレールはままつちょうえき 1 None 35.655 139.756944
データを以下のように修正します。
# 一括修正
df.loc[df["都道府県"]=="広島市", "都道府県"] = "広島県"
df.loc[df["都道府県"]=="阪堺電気軌道", "都道府県"] = "大阪府"
df.loc[df["都道府県"]=="名古屋市", "都道府県"] = "愛知県"
# nullを埋める
df.loc[df["駅名"]=="紙屋町西停留場", "都道府県"] = "広島県"
df.loc[df["駅名"]=="紙屋町東停留場", "都道府県"] = "広島県"
df.loc[df["駅名"]=="桜木町駅 (YOKOHAMA AIR CABIN)", "都道府県"] = "神奈川県"
df.loc[df["駅名"]=="陣屋町臨港駅", "都道府県"] = "北海道"
df.loc[df["駅名"]=="浜町アーケード停留場", "都道府県"] = "長崎県"
df.loc[df["駅名"]=="本町一丁目停留場", "都道府県"] = "愛媛県"
df.loc[df["駅名"]=="町屋駅前停留場", "都道府県"] = "東京都"
df.loc[df["駅名"]=="モノレール浜松町駅", "都道府県"] = "東京都"
次にラベルに関するデータを確認します。
df[(df["ちょう1まち2"]==0)|(df["ちょう1まち2"]==3)]
駅名 かな ちょう1まち2 都道府県 緯度 経度
3 青山町駅 あおやまちょうえき・近鉄大阪線 0 三重県 34.672847 136.177764
5 曙町東町停留場 あけぼのちょうひがしまちていりゅうじょう 0 高知県 33.551575 133.493408
7 旭町一丁目停留場 あさひまちいっちょうめていりゅうじょう 0 高知県 33.556742 133.513814
8 旭町三丁目停留場 あさひまちさんちょうめていりゅうじょう 0 高知県 33.555722 133.506514
19 伊勢佐木長者町駅 いせざきちょうじゃまちえき 0 神奈川県 35.441083 139.633139
32 浮島町駅 うきしまちょうえき 0 神奈川県 35.522944 139.782944
81 勝山町停留場 かつやまちょうていりゅうじょう 0 愛媛県 33.841681 132.774867
85 銀山町停留場 かなやまちょうていりゅうじょう 0 広島県 34.393247 132.466906
91 上町一丁目停留場 かみまちいっちょうめていりゅうじょう 0 高知県 33.557411 133.525464
92 上町五丁目停留場 かみまちごちょうめていりゅうじょう 0 高知県 33.557253 133.517064
93 上町二丁目停留場 かみまちにちょうめていりゅうじょう 0 高知県 33.557406 133.523358
94 上町四丁目停留場 かみまちよんちょうめていりゅうじょう 0 高知県 33.557369 133.520067
100 萱町六丁目停留場 かやまちろくちょうめていりゅうじょう 0 愛媛県 33.8512 132.756297
101 辛島町停留場 からしまちょうていりゅうじょう 0 熊本県 32.799014 130.704958
128 小伝馬町駅 こでんまちょうえき 0 東京都 35.69075 139.778472
213 高島町駅 たかしまちょうえき 0 神奈川県 35.458583 139.62375
218 谷町九丁目駅 たにまちきゅうちょうめえき 0 大阪府 34.667144 135.515842
219 谷町四丁目駅 たにまちよんちょうめえき 0 大阪府 34.681914 135.517286
220 谷町六丁目駅 たにまちろくちょうめえき 0 大阪府 34.674917 135.516958
232 長者町駅 ちょうじゃまちえき 0 千葉県 35.295861 140.385
244 伝馬町駅 てんまちょうえき・名古屋市営地下鉄名城線 0 愛知県 35.120833 136.910556
245 天満町停留場 てんまちょうていりゅうじょう・広島電鉄本線 0 広島県 34.3951 132.440878
260 長町一丁目駅 ながまちいっちょうめえき 0 宮城県 38.234228 140.887486
262 中町(西町北)停留場 なかまち(にしちょうきた)ていりゅうじょう 0 富山県 36.690306 137.215722
265 西辛島町停留場 にしからしまちょうていりゅうじょう 0 熊本県 32.798639 130.701444
286 浜町駅 はまちょうえき 0 東京都 35.688472 139.788139
290 播磨町駅 はりまちょうえき 0 兵庫県 34.716561 134.8681
303 福島町停留場 ふくしまちょうていりゅうじょう 0 広島県 34.394875 132.433975
328 本町一丁目停留場 ほんまちいっちょうめていりゅうじょう 0 愛媛県 33.840139 132.758339
329 本町五丁目停留場 ほんまちごちょうめていりゅうじょう 0 愛媛県 33.850653 132.758836
330 本町三丁目停留場 ほんまちさんちょうめていりゅうじょう 0 愛媛県 33.845158 132.758825
331 本町四丁目停留場 ほんまちよんちょうめていりゅうじょう 0 愛媛県 33.847956 132.758822
332 本町六丁目停留場 ほんまちろくちょうめていりゅうじょう 0 愛媛県 33.853322 132.758892
337 町屋二丁目停留場 まちやにちょうめていりゅうじょう 0 東京都 35.743694 139.776944
359 皆実町二丁目停留場 みなみまちにちょうめていりゅうじょう 0 広島県 34.377836 132.466103
360 皆実町六丁目停留場 みなみまちろくちょうめていりゅうじょう 0 広島県 34.3742 132.464058
(さすがに「町」を「ちょう」「まち」以外で読む駅はないようですね)
それでは、ラベルを以下のように修正します。
# データを見ると、青山町(あおやまちょう)などのように"○○まちょう"は、"まち"も"ちょう"も含む判定になっている
# →"ちょう"判定に修正
df.loc[df["かな"].str.contains("まちょう"), "ちょう1まち2"] = 1
# "丁"を含み、「ちょう1まち2」が0のデータは"まち"
df.loc[(df["駅名"].str.contains("丁"))&(df["ちょう1まち2"]==0), "ちょう1まち2"] = 2
# ちょうじゃまち駅なので"まち"
df.loc[df["駅名"]=="伊勢佐木長者町駅", "ちょう1まち2"] = 2
df.loc[df["駅名"]=="長者町駅", "ちょう1まち2"] = 2
df[(df["ちょう1まち2"]==0)|(df["ちょう1まち2"]==3)]
駅名 かな ちょう1まち2 都道府県 緯度 経度
5 曙町東町停留場 あけぼのちょうひがしまちていりゅうじょう 0 高知県 33.551575 133.493408
262 中町(西町北)停留場 なかまち(にしちょうきた)ていりゅうじょう 0 富山県 36.690306 137.215722
「町」を2つ含んで、それぞれ別の読み方をする駅が2つあるんですね…。この2つは例外的に除くことにします。
「ちょう」と「まち」どちらが多い?
とりあえず「ちょう」読むか「まち」と読むかどちらが多いかだけでも確認してみます。df = df[df["ちょう1まち2"]!=0] #曙町東町停留場と中町(西町北)停留場を除いた
print(f'「町」のつく駅の総数: {len(df)}')
print(f'「ちょう」と読む駅の数: {len(df[df["ちょう1まち2"]==1])}')
print(f'「まち」と読む駅の数: {len(df[df["ちょう1まち2"]==2])}')
print(f'「ちょう」と読む駅の割合: {len(df[df["ちょう1まち2"]==1])/len(df)}')
print(f'「まち」と読む駅の割合: {len(df[df["ちょう1まち2"]==2])/len(df)}')
「町」のつく駅の総数: 387
「ちょう」と読む駅の数: 158
「まち」と読む駅の数: 229
「ちょう」と読む駅の割合: 0.4082687338501292
「まち」と読む駅の割合: 0.5917312661498708
「ちょう」は約4割、「まち」が6割のようです。ちなみに「まち」と読む割合が7割をこえる都道府県は以下の通りです。
| 都道府県 | 町のつく駅 | まちと読む駅 | まちと読む割合 |
|---|---|---|---|
| 宮城県 | 12 | 10 | 0.833333 |
| 山形県 | 1 | 1 | 1.000000 |
| 福島県 | 5 | 5 | 1.000000 |
| 群馬県 | 5 | 5 | 1.000000 |
| 埼玉県 | 2 | 2 | 1.000000 |
| 新潟県 | 6 | 6 | 1.000000 |
| 富山県 | 21 | 15 | 0.714286 |
| 石川県 | 1 | 1 | 1.000000 |
| 福井県 | 4 | 4 | 1.000000 |
| 長野県 | 9 | 7 | 0.777778 |
| 三重県 | 7 | 5 | 0.714286 |
| 滋賀県 | 2 | 2 | 1.000000 |
| 京都府 | 7 | 6 | 0.857143 |
| 兵庫県 | 10 | 8 | 0.800000 |
| 島根県 | 2 | 2 | 1.000000 |
| 愛媛県 | 17 | 12 | 0.705882 |
| 福岡県 | 5 | 5 | 1.000000 |
| 佐賀県 | 1 | 1 | 1.000000 |
| 長崎県 | 14 | 14 | 1.000000 |
| 大分県 | 1 | 1 | 1.000000 |
| 宮崎県 | 2 | 2 | 1.000000 |
『100%「まち」と読む県』が九州に多いようです。
foliumで位置の図示化
それではfoliumを使って位置を図示化してみます。map_station = folium.Map(location=[36.000385797, 137.999954223], zoom_start=5)
for i, r in df[df["ちょう1まち2"]==1].iterrows():
folium.Marker(
location=[r["緯度"], r["経度"]],
popup=r["駅名"],
icon=folium.Icon(color='red')
).add_to(map_station)
for i, r in df[df["ちょう1まち2"]==2].iterrows():
folium.Marker(
location=[r["緯度"], r["経度"]],
popup=r["駅名"],
icon=folium.Icon(color='blue')
).add_to(map_station)
# htmlとして保存する場合は以下を実行
map_station.save("map_station.html")
map_station
自治体の「ちょう」「まち」のときように、きれいな境界線は無いようですね。このままだとSVMのような機械学習で判別するのは難しそうです。ちなみに、大阪付近では何となく「ちょう」「まち」の境界らしきものは見つかりました。県単位で「ちょう」「まち」判別する方法があるかもしれません。


