📍

施設名と地名の差をみつける

2022/12/04に公開

「ゆるWeb勉強会@札幌 2022年アドベントカレンダー」の4日目の記事です。Webなのか怪しいですけど・・・。
https://adventar.org/calendars/7513

ネタ

お店の名前やマンション名などに地名が入っていることは珍しくないと思いますが、特に有名だったりブランドがある地名だと、住所上の範囲を超えてその地名を名乗っている例を見かけませんか?

アドベントカレンダー的に例を札幌ローカルに激しく寄せて行きますが、例えば「北5条手稲通(旧5号線)」では、南側が宮の森、北側が二十四軒というエリアがあります。宮の森はブランド力の高い地名とされています(たぶん)。そのためか、宮の森を名前に含む施設が二十四軒側に染み出しています。[1]

こういうのを探して地図にプロットしてみます。

なお、はみ出す理由は有名さやブランドだけでなく、歴史的な事情が関係していることも多いです。それも見えてくるかもしれません。

成果物 (Streamlit)

ここから自由にさわれます。
https://shimat-place-name-to-location-main-u897kf.streamlit.app/

以下の例は、「吉祥寺」が名前に入る施設の位置と、吉祥寺の住所上の範囲の赤枠を示しています。赤枠の中の施設は除外しています。この例では、西側(武蔵野市内の別地名)や北側(練馬区側)などでも吉祥寺を名乗るスポットがあるとわかります。

すっかり手になじんだStreamlitです。Streamlit自体の詳しい説明はしません(過去に多少書きました)。

ソースコードはこちら: https://github.com/shimat/place_name_to_location

実装

施設名を検索する

今回はYahoo!ローカルサーチAPIを使用しました。
https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/localsearch.html

特定の緯度経度周辺の施設を簡単に検索できます。他のAPI含め、無料ながら結構な情報が得られてありがたいです。

課題

はじめに断っておきます。このAPIの性格上仕方ないですがおよそ商業施設しか検索できません [2]。マンション・アパートが地名を冠することは相当多いので、片手落ちな結果になることは覚悟します。

Google Maps APIならできそうですが、今回はお金の心配をせず遊ぶことを優先しました。

APIにリクエスト

例えば以下は、仙台駅(北緯38.25995878090344, 東経140.88253630445837)周辺で「牛タン」で検索する例です。アプリケーションIDの取得方法は、上記リファレンスに説明されておりご参照ください。

import requests

YAHOO_APPLICATION_ID = "..."

params = {
    "appid": YAHOO_APPLICATION_ID,
    "output": "json",
    "query": "牛タン",
    "lat": 38.25995878090344,
    "lon": 140.88253630445837,
    "dist": 1, # 周囲1km
    "detail": "standard",
    "results": 100,
    "start": 1}
response = requests.get("https://map.yahooapis.jp/search/local/V1/localSearch", params=params)
result = response.json()
レスポンスJSONの例
{
  "ResultInfo": {
    "Count": 100,
    "Total": 567,
    "Start": 1,
    "Status": 200,
    "Description": "",
    "Copyright": "",
    "Latency": 0.123
  },
  "Feature": [
    {
      "Id": "1111111111",
      "Gid": "gpbgMRtDdvY",
      "Name": "ほげほげ牛タン",
      "Geometry": {
        "Type": "point",
        "Coordinates": "38.25995878090344,140.88253630445837"
      },
      "Category": [],
      "Description": "",
      "Style": [],
      "Property": {
        "Uid": "...",
        "CassetteId": "...",
        "Yomi": "ホゲホゲギュウタン",
        "Country": {
          "Code": "JP",
          "Name": "日本"
        },
        "Address": "宮城県仙台市宮城野区榴岡1丁目1−1",
        "GovernmentCode": "01101",
        "AddressMatchingLevel": "6",
        "Tel1": "022-222-2222",
        "Genre": [
          {
            "Code": "0123001",
            "Name": "ファミレス"
          }
        ],
        "Station": [ ... ],
        "SmartPhoneCouponFlag": "false"
      }
    },
    ...
  ]
}

結果はAPIの仕様上最大3000件得ることができますが、1回のリクエストでは100件が上限です。すべて取得したければ、以下のようにstartをずらしながら複数回リクエストします。ここまでを関数にまとめます。

import requests
from time import sleep
from typing import Any

YAHOO_APPLICATION_ID = "..."

def request_yahoo_local_search(query: str, latlon: tuple[int, int], dist: int) -> dict[Any]:
    params = {
        "appid": YAHOO_APPLICATION_ID,
        "output": "json",
        "query": query,
        "lat": latlon[0],
        "lon": latlon[1],
        "dist": dist,
        "detail": "standard",
        "results": 100,
        "start": 1}
    r = requests.get(YAHOO_API_URL, params=params)
    r.raise_for_status()

    j: dict[Any] = r.json()
    total: int = min(j["ResultInfo"]["Total"], 3000)
    while len(j["Feature"]) < total:
        sleep(0.5)
        params["start"] += 100
        r = requests.get(YAHOO_API_URL, params=params)
        r.raise_for_status()
        j["Feature"].extend(r.json()["Feature"])
    return j

アプリケーションIDの管理

上記 YAHOO_APPLICATION_ID のような秘匿したい情報をGitHubにコミットするのはまずいので、Streamlitでは以下手引きに従い管理します。
https://docs.streamlit.io/streamlit-cloud/get-started/deploy-an-app/connect-to-data-sources/secrets-management

以下のように定義しておけば、コードからは st.secrets.yahoo_credentials.application_id のようにしてアクセスできます。

[yahoo_credentials]
application_id = "..."

開発時は、.streamlit/secrets.toml というファイルを作って書いておけば読み込んでくれます。くれぐれもコミットしないようにしましょう。即.gitignoreに登録します。

.gitignore
/.streamlit/secrets.toml

地図にプロットする

見つかった施設の位置を地図にして示します。

Streamlit標準のst.mapはやや表現力に欠けるので、streamlit-foliumを使用しました。
https://github.com/randyzwitch/streamlit-folium

Foliumによる地図をStreamlitに埋め込めるようにしてくれます。Foliumはleaflet.jsをPythonから扱いやすくしてくれるものです。

以下で地図がStreamlitに表示されます。

import folium
from streamlit_folium import folium_static

map = folium.Map(
    location=(35.36591060677768, 138.72951178453027), 
    zoom_start=14)
folium_static(map)

マーカーの追加

folium.Marker(
    location=(36.35578398203155, 138.72035983267511),
    tooltip=f"ほげほげ<br/>ぴよぴよ"
).add_to(map)

その他のオプションはこちらを参照: https://python-visualization.github.io/folium/modules.html#folium.map.Marker

直線の追加

地名の範囲を示すために使います。

その他のオプションはこちらを参照:https://python-visualization.github.io/folium/modules.html#folium.features.ColorLine

positionsには任意の長さの座標列を指定できます。多角形として閉じはしないので、たとえば四角形をつくりたければ始点に戻ってくるように5点を指定します。

colorscolormapの仕様が全然わかりません。とりあえずcolorsにはlen(positions)と同じ長さのlistかtupleが必要です。この例だと赤い線になります。

folium.ColorLine(
    positions=((36.4, 138.7), (36.5, 138.8)),
    colors=(0, 0),
    colormap=("r", "g", "b"),
    weight=7
).add_to(map)

ちなみに今回、地名の境界の座標は手作業で集めました。市町村の輪郭データは得やすいものの、市町村内の地区の輪郭情報がまとまったものが手に入れにくかったためです[3]。つらい・・・
https://github.com/shimat/place_name_to_location/blob/b17846028b5af2329ab9bf8e6861dcfbb4688e11/constants.py#L48

クレジット表示

Yahoo!デベロッパーネットワークで提供されるAPIを使用した場合は、アプリケーションにクレジット表記が必要です。
https://developer.yahoo.co.jp/attribution/

アプリケーションの最下部に、定められたHTMLコードまたはプレーンテキストそのままで出力するようにします。HTMLを使用する場合は、st.textまたはst.markdownunsafe_allow_html=Trueを使います。

st.markdown("""
-----
<!-- Begin Yahoo! JAPAN Web Services Attribution Snippet -->
<span style="margin:15px 15px 15px 15px"><a href="https://developer.yahoo.co.jp/sitemap/">Web Services by Yahoo! JAPAN</a></span>
<!-- End Yahoo! JAPAN Web Services Attribution Snippet -->
""", unsafe_allow_html=True)

結果を見ていく

技術の話はここまでで、以降は素人の適当な考察を書いていきます。アドベントカレンダー的に札幌の例を多くしていますが、少しだけほかの例もありますのでよければご覧ください。

例1: 宮の森

記事の序盤で例にした宮の森です。

北の二十四軒側にもはみ出ていますが、それよりも東側に集中しています。ここには地下鉄西28丁目駅があり、そもそもお店が多いという影響はありそうです。ただ、ここに出てこないマンションを別で見てみると「北円山」「円山北(町)」等と名乗る物件が多く、宮の森を冠するものはぱっと見つけられませんでした。

マンションの名前は決まりがある、というのがその理由かもしれません。簡単に言えば、所在地ではない名前を勝手に付けてはダメなのです。

商業施設はこういう規定は無いのでしょうか?調べられていませんが、結果からは無さそうに思えます。

参考: 宮の森の外れ値

ちなみに、この試みは遠く離れた場所でのヒットを眺めるのも楽しいです。[4]

一番遠いヒットは北西の宮の沢駅付近にある、宮の森スポーツ倶楽部 宮の沢校です。チェーン店のような業態でありこれは許す(?)でいい気がしてきますが、宮の沢に宮の森があるのは結構紛らわしいんですよね。ほかに宮の森珈琲もこれで遠距離でヒットします。

南東の中島公園そばのは「結婚相談所札幌宮の森良縁センター」だそうで、これはチェーン店でもない模様なので一番地名を頼りにしている感じがします(悪く言う意図はありません)。

参考: 二十四軒での結果

はみ出された側のお隣、二十四軒からの反撃具合はどうかというと、

なんと1つしか見つかりませんでした。その1つ「セブン‐イレブン札幌北9条二十四軒通店」も、通りの名前が付いているだけで無難(?)です。

そもそも枠内含めたヒット総数も26件と少なく、しかし歩くとそれなりにお店はありそうに思うので、特に商業施設にとっては「二十四軒」は名乗るに値しないということでしょうか・・・。マンションでは二十四軒を名乗るものは大量にありますが、これも前述の通り決まり上「致し方なく」なのかもしれません。宮の森との差をまざまざと見せつけられました。

と、だいぶ二十四軒をディスってしまいましたが、両隣(円山・琴似)が開発され尽くしたせいなのか最近再開発が盛んなようで、10年20年経つと変わっているかもしれませんね。

そもそも、「宮の森」は昔は「十二軒」という地名でした(参考)。十二軒と二十四軒の間柄だったのに、たまたま片方に皇族がお越しになって宮が付き、こんなことになりました。面白いものです。

例2: 琴似

次はお隣の琴似を見てみます。現代の住所から見れば、札幌では一番はみ出しているように感じられます[5]

赤枠が2022年現在の住所が琴似のエリアで、青枠は旧琴似町の範囲です。

赤枠から大量にはみ出していますが、いずれも旧琴似町ということで説明が付きそうです。私見では「琴似」にそんなにハイブランド性は感じないですが、とても著名で、広く一帯の地域名として親しまれている様子が伺えます。

中でも二十四軒と八軒では琴似を名乗りがちなのがわかります。赤枠すぐ北はJR琴似駅に近いことによるものでしょうが、更に北に離れた下手稲通方面にも琴似は多いです。

南側の山の手では少なく、「山の手」も一定のブランド性があるためかもしれません(たぶん)。ただ、琴似中学校が山の手にあるなど、山の手が琴似の一味という見方は一定程度ありそうです。

宮の森も旧琴似町です。琴似を名乗っているのが2件だけあり、ガソリンスタンドでした。ガソリンスタンドの店名はあまり誰も気にしないのかもしれませんね。政令指定都市になるタイミングで宮の森は中央区、琴似は西区と別れてしまい、そのせいか現代では琴似成分は希薄に見えます。

西隣の発寒は、おなじ西区にも関わらず同様に琴似成分が少なく、私の実感とも一致します。川を隔てると別の街ということなのか、発寒も歴史ある集落ということなのか、ともかく住民の意識として発寒は琴似ではないようです。[6]

旧手稲町側にはみ出す例はほぼありませんが、北海道日産の琴似店が宮の沢にあるのはなぜなんでしょうね...

例3: 山鼻

札幌市中央区の南の方を指しますが、2022年現在の住所にはありません。どのへんが山鼻だと思われているでしょうか。

山鼻の正確な定義は難しいですが、例えば以下市のホームページが参考になります。[7]

とはいえ図が小さすぎて詳しい境界はわからず、赤線は適当に引いてあります。[8]

「山鼻」が付く施設をプロットしてみると、だいたい南9条あたりが北端で、南23条あたり(自衛隊の北)が南端に見えます。ただマンションではさらに南にもあるようで、単にお店が少ないのかもしれません。南30条、ミュンヘン大橋あたりまでいくとほぼ山鼻は途絶えて、「藻岩」が多くなります。

東西は市電がおよそ境界になっているようです。西側はややルーズですね。

道路の向きが山鼻と中心部で少しだけ傾きがずれているのはご承知かもしれません(参考)。ここから、この「山鼻direction」な一帯を山鼻とみなすならば、あまりこの赤枠には意味がなく南4条くらいまで山鼻といえて、だからマンションも問題なく山鼻を名乗れているのかもしれません。とはいえ南9条より北だと憚られるんでしょうかね。

例4: 軽井沢

最後に札幌を離れて別な例を。おそらく日本で一番はみ出していると思うのが軽井沢です。

赤枠は長野県の軽井沢町、青枠は群馬県の長野原町北軽井沢です。これら以外にある「軽井沢」が付く物件をプロットしました。

縮尺が今までと段違いで、軽井沢駅を起点にした場合で30kmくらい離れた場所も見つかりました。APIの限界20kmのため漏れている結果があるかもしれません。

群馬県側にも大量にあります。そもそも住所になっている長野原町の「北軽井沢」もすごいですが、隣の嬬恋村にもさらに大量に(北)軽井沢がヒットしています。北軽井沢は歴史があって既に100年くらいはそう呼ばれているようです。

西側の御代田町は「西軽井沢」として最近知られているらしく多数スポットが所在します。小諸や佐久まではみ出す例もあります。

東側も群馬県で、少ないですが東軽井沢・南軽井沢と名乗る物件があります。東西南北揃いましたね。ここまで圧倒的なネームバリューの例はほかにあるでしょうか。

今回のネタは、以前に北軽井沢に泊まった際に思い付き、最近旧5号線(宮の森)で思い出して書いてみた次第です。

参考文献

脚注
  1. ちなみに地図では示されていませんがロイヤルホストも宮の森店です: https://locations.royalhost.jp/116807 ↩︎

  2. 集合住宅名もわずかにヒットしている気はします。 ↩︎

  3. 例えばこちらから得られるので、全然可能で私のやる気の問題です: https://geoshape.ex.nii.ac.jp/search/ ↩︎

  4. APIは最大20kmまで検索可能です。 ↩︎

  5. この企画は白石などでもやろうと思ったものの、区の名前になっており影響が無視できないと考えました。たまたま"琴似区"にならず西区になったから企画に乗ったという事情はありそうです。 ↩︎

  6. ただし琴似工業高校は発寒にあります。 ↩︎

  7. さらにさかのぼって山鼻村などに起源があるのかもしれませんが、よくわかりませんでした。少なくともこの区分けは、昭和30年代の「札幌市行政区域図」まではさかのぼれるようです: http://keystonesapporo.blog.fc2.com/blog-entry-2151.html ↩︎

  8. 山鼻小・伏見小・幌南小・山鼻南小 の学区に大体相当しそうな気がしています: https://school.mapexpert.net/pgAreaMap?L=1101&N=札幌市中央区 ↩︎

Discussion