よちよちpython

独習 python/Qpython/Pydroid3/termux/Linux

【folium】複数の座標から中心座標を算出して地図を作成する

今回は、地図作成ライブラリfoliumで複数地点の中心座標を算出する方法をやります。

f:id:chayarokurokuro:20210730092759j:plain



参考リンク

  • foliumオフィシャル

folium — Folium 0.12.1 documentation


plugins — Folium 0.12.1 documentation



foliumでは最初にマップオブジェクトを作成する際、中心座標を与えなければなりません。できた地図にマーカーなどを載せていきデコレートしたりしていきますが、複数のマーカーの座標から中心座標が求められれば、地図の中心が点在するマーカーのちょうど真ん中になり見やすくなるはずです。



【実行環境】

  • Android
  • Termux
  • Python 3.9.6
  • Jupyter Notebook
  • 使用するライブラリ
    • Pandas1.2.5、Numpy1.12.1、folium0.12.1



目次



座標のデータを用意し、地図を作りながら見ていきます。



マーカー用の座標データ

import pandas as pd

# 座標(緯度・経度)のデータ
fname = 'latlng_list.csv'
# CSVファイル読み込み
df = pd.read_csv(fname, header=None)
df = df.rename(columns={0:"地名" ,1:"緯度", 2:"経度"})

# 絞り込み
latlng_df = df.iloc[34:36, :]

# 表示
latlng_df
地名 緯度 経度
34 平城京 34.690710 135.794281
35 平安京 35.011005 135.759831

このような座標データがあります。この2点にマーカーを差します。



複数の座標から中心座標を算出する

2ヶ所の中心座標を求めたいので、緯度と経度のそれぞれで平均値を出します。

Pandasで平均値を出すにはmean()を使うと簡単に出来ます。列で平均値を出したいので、引数にaxis=0を指定する。

# dfの列で平均値を算出
mean_data = latlng_df.mean(axis=0)

# 表示
print(type(mean_data))
mean_data
<class 'pandas.core.series.Series'>





緯度     34.850858
経度    135.777056
dtype: float64

2点の中心座標がSeriesで作られました。



地図作成

まずは基本となる地図を作ります。

# 地図オブジェクト作成
import folium
from folium import plugins

m = folium.Map(mean_data)

# 表示
m
Make this Notebook Trusted to load map: File -> Trust Notebook

座標はSeries型でも大丈夫のようです。(あとにあるように、マーカーを差す時はSeriesは使えない。)

zoom_startは指定しませんでしたのでデフォルト値の10です。

これでは中心がどこなのかわかりませんので、次はマーカーを差します。

# 中心座標にマーカーを追加
folium.Marker(
    location = mean_data,
    popup = "center"
).add_to(m)

# 追加後の地図表示
m
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

/data/data/com.termux/files/usr/tmp/ipykernel_24080/4033970411.py in <module>
      1 # 中心座標にマーカーを追加
----> 2 folium.Marker(
      3     location = mean_data,
      4     popup = "center"
      5 ).add_to(m)


/data/data/com.termux/files/usr/lib/python3.9/site-packages/folium/map.py in __init__(self, location, popup, tooltip, icon, draggable, **kwargs)
    275         super(Marker, self).__init__()
    276         self._name = 'Marker'
--> 277         self.location = validate_location(location) if location else None

(中略)

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

あら? マーカーの座標ではSeriesはでけまへんがなと怒られた。ならば、リストに変換する。

# 中心座標にマーカーを追加
folium.Marker(
    location = mean_data.tolist(),
    popup = "center"
).add_to(m)

# 追加後の地図表示
m
Make this Notebook Trusted to load map: File -> Trust Notebook

OK牧場

したらば、次は平城京平安京にマーカーを差します。何か変わったアイコンを差してみましょうかね!

# 平城京に差す
folium.Marker(
    location = latlng_df.iloc[0, 1:3].tolist(),
    icon = plugins.BeautifyIcon(border_color='#00ea47',
                               text_color='#03ff04',
                               number=1,
                               inner_icon_style='margin-top:0;')

).add_to(m)
<folium.map.Marker at 0x73f87eaa90>
# 平安京に差す
folium.Marker(
    location = latlng_df.iloc[1, 1:3].tolist(),
    icon = plugins.BeautifyIcon(border_color='#e00e19',
                               text_color='#ff5204',
                               number=2,
                               inner_icon_style='plane')

).add_to(m)
<folium.map.Marker at 0x73f88b6d60>
# 地図表示
m
Make this Notebook Trusted to load map: File -> Trust Notebook

中心座標は真ん中に来ているようですね。

もう少し座標を増やして中心を決定する

新規に地図を作成します。マーカーの座標を増やして今までと同じことをやります。

# 座標データの用意
loc_df = df.query('地名 == ["山形駅","新鹿児島駅","高松駅","岩手駅"]')
# 表示
loc_df
地名 緯度 経度
37 山形駅 38.248926 140.327303
39 岩手駅 39.701437 141.136723
41 新鹿児島駅 31.583785 130.541245
44 高松駅 34.350680 134.046928

この4点の中心座標を算出し、地図のベースを作成します。
そこにマーカーを差します。

# 中心座標の算出
center = loc_df.mean(axis=0).tolist()

# 地図を作成
map = folium.Map(
    location = center,
    zoom_start = 3
)


# 地図の中心座標に赤色のマーカーを差す

folium.Marker(
    location = center,
    popup = "中心点",
    icon = folium.Icon(color="red")
).add_to(map)


# 他の4点のマーカーを緑で差す

# 4点の座標配列
latlngs = loc_df.iloc[:,1:3].values.tolist()

# 4点の地名配列(popup用)
names = loc_df['地名'].values.tolist()

# 4点のマーカーを差す
for latlng, name in zip(latlngs, names):
    folium.Marker(
        location = latlng,
        popup = name,
        icon = folium.Icon(color="green")
    ).add_to(map)
    
# 表示
map
Make this Notebook Trusted to load map: File -> Trust Notebook

できた。

folium.Marker()で使うマーカーの座標はDataFrame型やSeries型ではエラーが出る。よってリストに変換しているが、データフレーム型をリストにするにも一旦valuesto_numpy()を使ってデータの中身だけにしたあとtolist()で変換させた。いきなりtolist()だとエラー。

zoom_startの値もマーカーの座標の散らばり具合で自動的に変更できるようにすれば良くなると思うが、座標とzoom_startの表示範囲の関係がわからない。

最後にもう1つ。

地名 緯度 経度
134 福岡県庁 33.606314 130.418029
135 佐賀県 33.249439 130.298804
136 大分県 33.238200 131.612674
137 長崎県 32.750336 129.867908
138 熊本県 32.789826 130.741478
139 宮崎県庁 31.910908 131.423898
140 鹿児島県庁 31.560183 130.557968
141 沖縄県 26.212523 127.680771



Make this Notebook Trusted to load map: File -> Trust Notebook



赤色のマーカーが中心に来ているかな? 沖縄が遠すぎる気が…



  • 参考リンク

【folium】地図のMarkerの色や形・アイコン・タイルを変える - よちよちpython



今回は以上です。