はじめに
今回はPythonで地図を活用したデータの可視化というテーマでコードを組んでいきます。Pythonでデータの可視化といえば代表的なライブラリとしてMatpoltlib
やSeaborn
が挙げられますが,今回はfolium
というライブラリを使用します。folium
は地図を用いたデータの可視化をする際にとても便利なライブラリです。folium
の機能や詳しい使い方について今回は触れていません。以下のサイトで様々な機能が紹介されていますので自身で手を動かして遊んでみると面白いと思います!
実行環境
今回は以下の実行環境を使用しています。
・Windows 11
・Python 3.10.12
・folium 0.14.0
地下鉄の駅と家賃相場を地図に可視化させてみる
今回は名古屋市営地下鉄の駅と各駅の家賃相場を地図に可視化させていきます。
※家賃データはこちらのサイトのワンルーム・1K・1DK/マンションの相場表の家賃相場を参考にしています。
地図の紹介と解説
まず最初に作成した地図を紹介します。
この地図について簡単に解説します。まず,地図上で各駅の場所が分かるようにマーカーをプロットしています。各駅のマーカーの色はその駅が属する路線の色に対応しています。各駅のマーカの下にある色のついた円はその駅の家賃相場をヒートマップで表した色であり,赤色に近づくほど価格が高く,反対に青色に近づくほど価格が低いことを表しています。この地図からは名古屋駅や栄駅周辺の中心地は家賃相場が高く,中心部から離れた駅の家賃相場は比較的低いことが読み取れます。
コードの紹介と解説
次に今回使用したコードを紹介します。
import folium
from folium.plugins import MarkerCluster, HeatMap
m = folium.Map(location=[35.1709, 136.8815], zoom_start=13)
folium.LatLngPopup().add_to(m)
mcg = MarkerCluster(control=False, maxClusterRadius=1)
m.add_child(mcg)
g1 = folium.plugins.FeatureGroupSubGroup(mcg, "名城線")
g2 = folium.plugins.FeatureGroupSubGroup(mcg, "桜通線")
g3 = folium.plugins.FeatureGroupSubGroup(mcg, "東山線")
g4 = folium.plugins.FeatureGroupSubGroup(mcg, "鶴舞線")
m.add_child(g1)
m.add_child(g2)
m.add_child(g3)
m.add_child(g4)
stations = [
{"name": "大曽根駅","location": [35.193356, 136.937801],"rent_price":61400,"line": "名城線"},
{"name": "平安通駅","location": [35.1960, 136.9298],"rent_price":60500,"line": "名城線"},
{"name": "志賀本通駅","location": [35.1962, 136.9213],"rent_price":55900,"line": "名城線"},
{"name": "黒川駅","location": [35.1971, 136.9093],"rent_price":55800,"line": "名城線"},
{"name": "名城公園駅","location": [35.19, 136.90395],"rent_price":52500,"line": "名城線"},
{"name": "名古屋城駅","location": [35.18153, 136.9054],"rent_price":74400,"line": "名城線"},
{"name": "久屋大通駅","location": [35.17368, 136.90818],"rent_price":67400,"line": "名城線"},
{"name": "栄駅","location": [35.1693, 136.9086],"rent_price":64800,"line": "名城線"},
{"name": "矢場町駅","location": [35.16291, 136.90913],"rent_price":60800,"line": "名城線"},
{"name": "上前津駅","location": [35.157297, 136.906806],"rent_price":61300,"line": "名城線"},
{"name": "東別院駅","location": [35.14992, 136.90381],"rent_price":62700,"line": "名城線"},
{"name": "金山駅","location": [35.143667, 136.900806],"rent_price":60400,"line": "名城線"},
{"name": "西高蔵駅","location": [35.13419, 136.90205],"rent_price":54700,"line": "名城線"},
{"name": "熱田神宮西駅","location": [35.12793, 136.90666],"rent_price":55800,"line": "名城線"},
{"name": "熱田神宮伝馬町駅","location": [35.12063, 136.91051],"rent_price":47700,"line": "名城線"},
{"name": "堀田駅","location": [35.11647, 136.92196],"rent_price":51300,"line": "名城線"},
{"name": "妙音通駅","location": [35.11717, 136.92944],"rent_price":49300,"line": "名城線"},
{"name": "新瑞橋駅","location": [35.11738, 136.93668],"rent_price":52400,"line": "名城線"},
{"name": "瑞穂運動場東駅","location": [35.12212, 136.94778],"rent_price":56400,"line": "名城線"},
{"name": "総合リハビリセンター駅","location": [35.1307, 136.95482],"rent_price":43500,"line": "名城線"},
{"name": "八事駅","location": [35.13672, 136.96428],"rent_price":45100,"line": "名城線"},
{"name": "八事日赤駅","location": [35.14551, 136.96496],"rent_price":43700,"line": "名城線"},
{"name": "名古屋大学駅","location": [35.15425, 136.96672],"rent_price":48200,"line": "名城線"},
{"name": "本山駅","location": [35.1636, 136.96374],"rent_price":57200,"line": "名城線"},
{"name": "自由が丘駅","location": [35.17433, 136.96672],"rent_price":54800,"line": "名城線"},
{"name": "茶屋ヶ坂駅","location": [35.1844, 136.96248],"rent_price":54700,"line": "名城線"},
{"name": "砂田橋駅","location": [35.18858, 136.9552],"rent_price":57000,"line": "名城線"},
{"name": "ナゴヤドーム前矢田駅","location": [35.19375, 136.94758],"rent_price":59200,"line": "名城線"},
{"name": "太閤通駅","location": [35.1675, 136.8725],"rent_price":56000,"line": "桜通線"},
{"name": "名古屋駅","location": [35.1709, 136.8815],"rent_price":60900,"line": "桜通線"},
{"name": "国際センター駅","location": [35.1722, 136.8898],"rent_price":59900,"line": "桜通線"},
{"name": "丸の内駅","location": [35.1739, 136.8969],"rent_price":63000,"line": "桜通線"},
{"name": "久屋大通駅","location": [35.1739, 136.9081],"line": "桜通線"},
{"name": "高岳駅","location": [35.1741, 136.9156],"rent_price":64000,"line": "桜通線"},
{"name": "車道駅","location": [35.1734, 136.9295],"rent_price":63100,"line": "桜通線"},
{"name": "今池駅","location": [35.1690, 136.9370],"rent_price":57500,"line": "桜通線"},
{"name": "吹上駅","location": [35.1592, 136.9354],"rent_price":53800,"line": "桜通線"},
{"name": "御器所駅","location": [35.1495, 136.9337],"rent_price":52200,"line": "桜通線"},
{"name": "桜山駅","location": [35.1383, 136.9335],"rent_price":58500,"line": "桜通線"},
{"name": "瑞穂区役所駅","location": [35.1319, 136.9345],"rent_price":56100,"line": "桜通線"},
{"name": "瑞穂運動場西駅","location": [35.1248, 136.9355],"rent_price":51800,"line": "桜通線"},
{"name": "新瑞橋駅","location": [35.1178, 136.9366],"line": "桜通線"},
{"name": "桜本町駅","location": [35.1091, 136.9368],"rent_price":55100,"line": "桜通線"},
{"name": "鶴里駅","location": [35.1055, 136.9444],"rent_price":56000,"line": "桜通線"},
{"name": "野並駅","location": [35.1026, 136.9550],"rent_price":57500,"line": "桜通線"},
{"name": "鳴子北駅","location": [35.1026, 136.9655],"rent_price":47100,"line": "桜通線"},
{"name": "相生山駅","location": [35.1025, 136.9759],"rent_price":38700,"line": "桜通線"},
{"name": "神沢駅","location": [35.0983, 136.9896],"rent_price":46000,"line": "桜通線"},
{"name": "徳重駅","location": [35.0947, 136.9978],"rent_price":55400,"line": "桜通線"},
{"name": "高畑駅","location": [35.1390, 136.8535],"rent_price":52000,"line": "東山線"},
{"name": "八田駅","location": [35.1490, 136.8524],"rent_price":53300,"line": "東山線"},
{"name": "岩塚駅","location": [35.1583, 136.8544],"rent_price":50300,"line": "東山線"},
{"name": "中村公園駅","location": [35.1678, 136.8549],"rent_price":53000,"line": "東山線"},
{"name": "中村日赤駅","location": [35.1727, 136.8622],"rent_price":55900,"line": "東山線"},
{"name": "本陣駅","location": [35.1770, 136.8671],"rent_price":56500,"line": "東山線"},
{"name": "亀島駅","location": [35.1775, 136.8776],"rent_price":59700,"line": "東山線"},
{"name": "名古屋駅","location": [35.1705, 136.8810],"line": "東山線"},
{"name": "伏見駅","location": [35.1692, 136.8974],"rent_price":64900,"line": "東山線"},
{"name": "栄駅","location": [35.1700, 136.9084], "line": "東山線"},
{"name": "新栄町駅","location": [35.1707, 136.9202],"rent_price":62500,"line": "東山線"},
{"name": "千種駅","location": [35.1707, 136.9309],"rent_price":60400,"line": "東山線"},
{"name": "今池駅","location": [35.1686, 136.9369],"line": "東山線"},
{"name": "池下駅","location": [35.1678, 136.9460],"rent_price":59900,"line": "東山線"},
{"name": "覚王山駅","location": [35.1665, 136.9529],"rent_price":61900, "line": "東山線"},
{"name": "本山駅","location": [35.1633, 136.9638],"line": "東山線"},
{"name": "東山公園駅","location": [35.1604, 136.9729],"rent_price":57800,"line": "東山線"},
{"name": "星が丘駅","location": [35.1625, 136.9856],"rent_price":53500,"line": "東山線"},
{"name": "一社駅","location": [35.1681, 136.9960],"rent_price":53600,"line": "東山線"},
{"name": "上社駅","location": [35.1734, 137.0067],"rent_price":51100,"line": "東山線"},
{"name": "本郷駅","location": [35.1754, 137.0136],"rent_price":51800,"line": "東山線"},
{"name": "藤が丘駅","location": [35.1825, 137.0214],"rent_price":50500,"line": "東山線"},
{"name": "上小田井駅","location": [35.2235, 136.8769],"rent_price":49600,"line": "鶴舞線"},
{"name": "庄内緑地公園駅","location": [35.2150, 136.8867],"rent_price":48400,"line": "鶴舞線"},
{"name": "庄内通駅","location": [35.2038, 136.8911],"rent_price":51700,"line": "鶴舞線"},
{"name": "浄心駅","location": [35.1922, 136.8909],"rent_price":56500,"line": "鶴舞線"},
{"name": "浅間町駅","location": [35.1835, 136.8904],"rent_price":57500,"line": "鶴舞線"},
{"name": "丸の内駅","location": [35.1751, 136.8967],"line": "鶴舞線"},
{"name": "伏見駅","location": [35.1687, 136.8975],"line": "鶴舞線"},
{"name": "大須観音駅","location": [35.1615, 136.8982],"rent_price":61800,"line": "鶴舞線"},
{"name": "上前津駅","location": [35.1573, 136.9060],"line": "鶴舞線"},
{"name": "鶴舞駅","location": [35.1561, 136.9168],"rent_price":59400,"line": "鶴舞線"},
{"name": "荒畑駅","location": [35.1496, 136.9254],"rent_price":51600,"line": "鶴舞線"},
{"name": "御器所駅","location": [35.1491, 136.9337],"line": "鶴舞線"},
{"name": "川名駅","location": [35.1487, 136.9480],"rent_price":50100,"line": "鶴舞線"},
{"name": "いりなか駅","location": [35.1438, 136.9547],"rent_price":49100,"line": "鶴舞線"},
{"name": "八事駅","location": [35.1372, 136.9636],"line": "鶴舞線"},
{"name": "塩釜口駅","location": [35.1324, 136.9776],"rent_price":45200,"line": "鶴舞線"},
{"name": "植田駅","location": [35.1284, 136.9889],"rent_price":43700,"line": "鶴舞線"},
{"name": "原駅","location": [35.1261, 136.9964],"rent_price":45000,"line": "鶴舞線"},
{"name": "平針駅","location": [35.1226, 137.0072],"rent_price":43800,"line": "鶴舞線"},
{"name": "赤池駅","location": [35.1210, 137.0187],"rent_price":49600,"line": "鶴舞線"}
]
lines = [
{"group": g1, "line": "名城線", "color": "purple"},
{"group": g2, "line": "桜通線", "color": "red"},
{"group": g3, "line": "東山線", "color": "orange"},
{"group": g4, "line": "鶴舞線", "color": "blue"},
]
for line in lines:
for station in stations:
if station["line"] == line["line"]:
folium.Marker(
location=station["location"],
popup=station["name"],
icon=folium.Icon(color=line["color"]),
).add_to(line["group"])
heatmap_price = [(station["location"][0], station["location"][1], station["rent_price"]) for station in stations if "rent_price" in station]
heatmap = HeatMap(heatmap_price, radius=20, blur=1)
heatmap_group = folium.FeatureGroup(name="heatmap")
heatmap_group.add_child(heatmap)
m.add_child(heatmap_group)
folium.LayerControl(collapsed=False).add_to(m)
m
では具体的にコードの解説をしていきます。
folium
ライブラリとプラグインのインストール
まずはfolium
ライブラリと今回使用するプラグインをダウンロードしていきます。
import folium
from folium.plugins import MarkerCluster, HeatMap
1行目はfolium
ライブラリをインストールためのコードです。
MarkerCluster
は地図上にプロットするマーカーの種類分けに使用します。具体的にはこの✓ボックスが該当します。
MarkerCluster
を使用すると一部に着目したい時に有効です。
具体例を挙げると,名城線の駅の場所だけを見たい時には名城線のボックスだけに✓を入れれば名城線の駅のマーカーだけを地図上に表示することができます。
Heatmap
はデータを色で可視化する際に必要となります。今回の場合は上の地図のように各駅の家賃相場を色で表現し可視化する際に使用しています。
地図の生成と座標の表示機能の追加
m = folium.Map(location=[35.1709, 136.8815], zoom_start=13)
folium.LatLngPopup().add_to(m)
続いて地図を生成して,座標を表示する機能を追加します。1行目は特定の座標を中心に地図を表示するためのコードです。今回は名古屋駅の座標を中心としています。zoom_start
は最初にどの程度拡大して表示するかを決定します。今回は13に設定していますが個人の好みですのでお好みで設定してください。2行目はクリックした場所の座標を表示する機能を追加するコードです。今回は各駅の座標を調べる時に便利だったので使用しました。
MarkerCluster
の詳細な設定をする
続いてMarkerCluster
の設定をしていきます。
mcg = MarkerCluster(control=False, maxClusterRadius=1)
m.add_child(mcg)
g1 = folium.plugins.FeatureGroupSubGroup(mcg, "名城線")
g2 = folium.plugins.FeatureGroupSubGroup(mcg, "桜通線")
g3 = folium.plugins.FeatureGroupSubGroup(mcg, "東山線")
g4 = folium.plugins.FeatureGroupSubGroup(mcg, "鶴舞線")
m.add_child(g1)
m.add_child(g2)
m.add_child(g3)
m.add_child(g4)
MarkerCluster
は地図上にマーカーをグループ化して表示するためのクラスターを作成します。maxClusterRadius=1
はクラスタの最大半径を1にする設定です。
maxClusterRadius
の設定をしていない状態では上の地図のように近い距離にあるマーカー同士が1つのクラスターになってしまい正確に駅の場所を表示することができません。また地図を縮小するとよりマーカー同士がクラスターを形成していきます。今回は可能な限りクラスターを形成したくないので設定を1にしています。
g1 = folium.plugins.FeatureGroupSubGroup(mcg, "名城線")
これはマーカーのグループを作成するためのコードです。今回は路線ごとに表示できるようにするため路線名をグループにしています。名城線と同じように他の路線のグループも作成します。
m.add_child(g1)
このコードで作成したグループを地図に追加することができます。これも同様に他の路線も地図に追加します。
これらのコードを組むことで先ほど紹介したこのボックスが地図に追加されます。
駅リストの作成
続いて駅の情報を含んだリストを作成していきます。
stations = [
{"name": "大曽根駅","location": [35.193356, 136.937801],"rent_price":61400,"line": "名城線"},
#他の駅も同様に情報を入力していきます
]
{"name":"駅名","location":[緯度,経度],"rent_price":値段,"line":"路線名"},
という形で各駅の情報を入力していきます。緯度と経度の情報を取得する際には様々な方法があると思いますが今回は先ほど紹介したfolium.LatLngPopup().add_to(m)
で追加したクリックした場所の緯度と経度を表示する機能を活用して1駅ずつ地道に座標をリストに入力していきました。省略していますが大曽根駅に続いて他の駅の情報も入力していきます。コピペする場合は最初に紹介した全体のコードからお願いします。
読み込んだ情報を使って地図上にマーカーを追加する
ここまでで今回地図上に可視化させたい情報の準備がほぼできました。ここからは実際に地図上にマーカーを追加するためのコードを組んでいきます。
lines = [
{"group": g1, "line": "名城線", "color": "purple"},
{"group": g2, "line": "桜通線", "color": "red"},
{"group": g3, "line": "東山線", "color": "orange"},
{"group": g4, "line": "鶴舞線", "color": "blue"},
]
for line in lines:
for station in stations:
if station["line"] == line["line"]:
folium.Marker(
location=station["location"],
popup=station["name"],
icon=folium.Icon(color=line["color"]),
).add_to(line["group"])
この部分のコードについては自分の現段階の知識では詳細な解説をすることが難しいと感じたので理解している範囲で紹介します。ご了承ください。
まずはクラスターと各路線とマーカーの色を対応させていきます。
location
はマーカーを表示させる場所,popup
はマーカーをクリックした時に表示される文字,"color"
で指定する色は地図上に表示するマーカーの色になります。
例えば,このマーカーはlocation
は名古屋駅の座標,popup
は"名古屋駅","color"は'red'です。
HeatMap
の詳細な設定をする
最後にHeatMap
の生成と完成した地図を表示していきます
heatmap_price = [(station["location"][0], station["location"][1], station["rent_price"]) for station in stations if "rent_price" in station]
heatmap = HeatMap(heatmap_price, radius=20, blur=1)
heatmap_group = folium.FeatureGroup(name="heatmap")
heatmap_group.add_child(heatmap)
m.add_child(heatmap_group)
folium.LayerControl(collapsed=False).add_to(m)
m
1~5行目はHeatMap
の設定から地図への実装までのコードとなります。1行目はヒートマップを作成するためのデータを指定しています。station["location"][0] は駅の緯度、station["location"][1] は駅の経度、station["rent_price"]
は家賃価格を取得します。2行目では表示するヒートマップの半径や透明度の詳細な設定をします。3行目ではMarkerCluster
に"heatmap"という名前のグループを作成します。4行目では作成したヒートマップをMaekerCluster
の"heatmap"に追加します。5行目では作成したヒートマップと"heatmap"というクラスターを地図に追加します。
folium.LayerControl(collapsed=False).add_to(m)
は作成したクラスター機能を表示するためのコードです。最後にm
を実行して結果として作成した地図を表示します。
最後に
今回はfolium
というPythonのライブラリを使用して駅と家賃相場を地図に可視化させてみました。住所ごとの地価データを使えば名古屋市内全体の地価相場を可視化させることができ,実用的なものになるかなと感じました。folium
はもっと上手く使えばより実用的な地図データを作成することができると思います。今回の記事を読んでfolium
に興味をもってもらえたらなと思います!最後まで読んでいただきありがとうございました!