🗺️
【Python】地図上に位置情報(緯度・経度)をプロットする方法
Pythonを使って、緯度・経度の座標情報を地図上にプロットする方法についてご紹介します。
サンプルのデータとして、githubに公開されている米国の都市データを使いますので、ここに記載のコードをコピペすることで、お手元のPCでも同じものを見ることができます。
興味を持たれた方は、ぜひ、一緒にやってみてください。
地図に位置情報をプロットできるライブラリーとして、foliumとPlotlyの2種類あります。
それぞれについて、ご紹介していきます。
データのダウンロード
まずは、サンプルデータをダウンロードしましょう。
import pandas as pd
df =pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/us-cities-top-1k.csv")
df.dropna(inplace=True)
df
foliumバージョン
最初にご紹介するのは、foliumです。
地図情報といえば、foliumが一般的と思います。
コードもシンプルです。中心座標を指定する必要があるのが、少し面倒です。
import folium
#サイズを指定する
folium_figure = folium.Figure(width=1500, height=700)
# 初期表示の中心の座標を指定して地図を作成する。
center_lat=40
center_lon=-95
folium_map = folium.Map([center_lat,center_lon],
zoom_start=4.5).add_to(folium_figure)
# trainデータの300行目までマーカーを作成する。
for i in range(300):
folium.Marker(location=[df.loc[i, "lat"],
df.loc[i, "lon"]]).add_to(folium_map)
folium_map
マーカーが大きくて見やすい代わりに、多くの情報を一度に載せることは難しそうです(マーカーが重なってしまう)
Plotlyバージョン
インタラクティブにデータを可視化してくれることで有名なPlotlyです
単に位置情報をプロットする以外にも、いろいろ使い方があります
位置情報のみプロット
まずは、位置情報だけをプロットしてみましょう
import plotly.express as px
fig = px.scatter_mapbox(
# データフレームおよび緯度・経度の設定
data_frame=df,
lat="lat",
lon="lon",
#カーソルを当てるとホバーする情報を与えます
hover_data=["State","Population"],
zoom=4,
height=700,
width=1500)
fig.update_layout(mapbox_style='open-street-map')
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
fig.show()
ご覧のように、カーソルを当てると、緯度・経度の他に、州名・人口もホバーします。
人口の大きさに応じてマーカーの大きさを変える
続いて、人口の大きさに応じて、マーカー(円)の大きさを変えてみます。
これは便利な機能だと思います。
fig = px.scatter_mapbox(
# データフレームおよび緯度・経度の設定
data_frame=df,
lat="lat",
lon="lon",
# ホバー時の表示設定
hover_data=["Population"],
# 散布図のマーカーの設定
color="Population",
size="Population",
size_max=50,
opacity=0.3,
# 作図の設定
zoom=4,
height=700,
width=1500)
fig.update_layout(mapbox_style='open-street-map')
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
fig.show()
人口が大きい都市について、マーカーのサイズが大きくなっています。
クラスタリング
都市どうしの距離に応じて、クラスタリングしたうえで、クラスターを可視化してみます。
scikit-learnのkmeansを使います。
from sklearn.preprocessing import scale
from sklearn.cluster import KMeans
モデルをインスタンス化。クラスター数は10にしてみます。
#モデルの作成
model = KMeans(n_clusters=10,random_state=1234)
#データを正規化し、fit関数により訓練を実施
model = model.fit(df[["lat","lon"]])
df_model = pd.DataFrame(model.labels_)
df["cluster_id_location"] = df_model
ビジュアル化のための関数を用意しておきます。
def visualize_trafic(df, name_="cluster_id",zoom=4):
fig = px.scatter_mapbox(df,
# Here, plotly gets, (x,y) coordinates
lat="lat",
lon="lon",
#Here, plotly detects color of series
color=name_,
labels=name_,
zoom=zoom,
size_max = 30,
height=700,
width=1500)
fig.update_layout(mapbox_style='open-street-map')
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
fig.update_layout(title_text="GPS trafic")
fig.show()
可視化します。
visualize_trafic(df, name_="cluster_id_location")
綺麗にクラスタリングされていますね。
Discussion