0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【ちょうorまち】「町」がつく駅名をBeautifulSoupで取得、foliumで位置を図示化してみた

0
Last updated at Posted at 2021-08-06

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

長野あたりに境界ができるのは面白いですね。

私はこの記事を読んで、駅名でも「ちょう」と読むか「まち」と読むかの境界線があるかどうか気になりました。そこで、データの取得(スクレイピング)、簡単なデータ分析、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

map_station.jpg

map_station2.jpg

map_station3.jpg

自治体の「ちょう」「まち」のときように、きれいな境界線は無いようですね。このままだとSVMのような機械学習で判別するのは難しそうです。ちなみに、大阪付近では何となく「ちょう」「まち」の境界らしきものは見つかりました。県単位で「ちょう」「まち」判別する方法があるかもしれません。

まとめと今後

「町」がつく駅名のデータを取得し、foliumで「町」がつく駅名の位置を図示化してみました。もう少し時間があれば他のデータ等を利用して、よさげな「ちょう」「まち」の2値判別器を検討してみたいと思います。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?