plotly.expressパッケージのscatter_mapboxで地図に散布図を描いてみる

2021.08.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

データアナリティクス事業本部の鈴木です。

今回は、plotly.expressパッケージのscatter_mapbox関数を使って地図上でデータを可視化する方法をご紹介します。

plotly.express package documentation

scatter_mapbox関数は、緯度・経度を含むデータフレームを渡すことで、インタラクティブな地図上に散布図を描写できます。

「地図上に散布図を描写できる」と書いてしまうと、なにに使えるんだろう?と感じてしまうかもしれませんが、データを可視化する様々な場面で活躍します。

特に今回は以下の2つのケースを紹介します。

  1. 値の大きさに意味のあるデータの可視化
  2. 時系列データの可視化

検証環境

Jupyter Docker Stacksdatascience-notebookイメージにPlotlyをインストールして検証しました。バージョンなどは以下になります。

やってみる

1.値の大きさに意味のあるデータの可視化

まず、値の大きさに意味のあるデータのケースを紹介します。値の大きさに意味のあるとは、例えばある場所での人口や気温などです。

例として、ある年度の都道府県ごとの総人口をscatter_mapbox関数で可視化してみます。 データは以下のようなものです。

city_population.csv

code,city,latitude,longitude,population
0,sapporo,43.06415035,141.34676496,1952356
1,aomori,40.82443999,140.74000496,287648
2,morioka,39.70356954,141.15265155,297631
3,sendai,38.2688808,140.87198085,1082159
4,akita,39.718624,140.102386,315814
5,yamagata,38.24055033,140.36335772,253832
(略)
46,naha,26.21244491,127.6809218,319435

このデータのpopulationカラムは2015年度の県庁所在地の総人口で、政府統計の総合窓口(e-Stat)から取得しました。東京都の人口は、23区の人口の和になります。latitudeおよびlongitudeは地理院地図で県庁所在地付近の位置情報を取得しました。

このCSVをpandasでデータフレームとして読み出し、scatter_mapbox関数で可視化してみましょう。

import pandas as pd
import plotly.express as px

df_city_population = pd.read_csv("./city_population.csv")

fig = px.scatter_mapbox(
    # データフレームおよび緯度・経度の設定
    data_frame=df_city_population,
    lat="latitude",
    lon="longitude",
    # ホバー時の表示設定
    hover_name="city",
    hover_data=["population"],
    # 散布図のマーカーの設定
    color="population",
    size="population",
    size_max=30,
    opacity=0.4,
    # 作図の設定
    center={'lat':34.686567, 'lon':135.52000},
    zoom=4,
    height=600,
    width=800)
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="Population of each cities")
fig.show()

実行すると、以下のように県庁所在地の位置に、各都道府県の人口ごとに色と大きさが異なるマーカーを表示することができました。今回は静止画ですが、インタラクティブに操作が可能です。

各都市の総人口

各引数は以下を指定します。

  • data_frame: 処理対象のデータフレーム
  • lat: 緯度を表すカラムの名前
  • lon: 経度を表すカラムの名前
  • color: マーカーの色を決めるカラムの名前
  • size: マーカーの大きさを決めるカラムの名前
  • size_max: マーカーの大きさの上限
  • opacity: マーカーの不透明度
  • center: 地図を表示する際の中心の初期値
  • zoom: 地図を表示する際の縮尺の初期値
  • height:図の高さ
  • width:図の幅

また、mapbox_styleでopen-street-mapを指定しました。この値により、使用する地図タイルを選択することができます。

hover_nameとhover_dataは、以下のようにデータ点をホバーした際の表示の制御を行います。

ホバー時の表示

2.時系列データの可視化

次に時系列データケースを紹介します。具体的にはGPSで取得した位置情報を想定しています。

今回は秋葉原駅からぐるっと散歩して、駅の別の入り口に戻ったとして、その軌跡を可視化してみます。

データは以下のようなCSV(trajectory1.csv)を準備しました。

trajectory1.csv

x,y
35.697582,139.772637
35.697579,139.772401
35.697580,139.772191
35.697573,139.771953

データは地理院地図で各地点の緯度・経度を取得しました。このデータとは別にもう一つ別経路のデータ(trajectory2.csv)も作成しました。

以下のコードで可視化してみましょう。

# データの読み込み
df_gps1 = pd.read_csv("./trajectory1.csv")
df_gps2 = pd.read_csv("./trajectory2.csv")

# データごとにラベルを表すカラムを作成した後、1つのデータフレームにまとめる
df_gps1["trajectory"] = "trajectory1"
df_gps2["trajectory"] = "trajectory2"
df_gps = pd.concat([df_gps1, df_gps2])

# データを可視化する
fig = px.scatter_mapbox(
    # データフレームおよび緯度・経度の設定
    data_frame=df_gps,
    lat="x",
    lon="y",
    # ホバー時の表示設定
    hover_name="trajectory",
    # 散布図のマーカーの設定
    color="trajectory",
    opacity=1.0,
    # 作図の設定
    center={'lat':35.697582, 'lon':139.772637},
    zoom=15,
    height=600,
    width=800)
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 trajectories")
fig.show()

今回は縮尺に対して相対的にデータ間の距離が開いているので、画像ではちょっと見にくくなってしまっていますが、移動した軌道が可視化されていることが分かります。

GPSデータの描写例

※今回のデータだと縮尺を小さくすると軌跡が見やすくなりました。 GPSの軌跡2

OpenStreetMapに可視化することで、データ系列と地理情報の関係性もよく分かるようになります。インタラクティブな地図なので、拡大・縮小やスライドすることも可能です。

最後に

plotly.expressパッケージのscatter_mapboxを使ったデータの可視化例を紹介しました。

特にGPSで取得した位置情報の軌跡ような時系列データを可視化する際に、とても簡単に、分かりやすいインタラクティブプロットが描写できるのでとても気に入っています。

plotly.expressパッケージにはscatter_mapboxのほかにも地理的なデータの可視化に使える関数があるので、ぜひ利用してみてください。