はじめに
10月にリリースされた Streamlit 1.39.0 から、st.pydeck_chart
による地図描画で、選択した点を取得できるようになりました。
今回は、そちらの機能の紹介と、簡単なデモアプリを紹介しようと思います。
概要
st.pydeck_chart
の紹介
st.pydeck_chart
は、PyDeck ライブラリを Streamlit アプリ内で使用して、地図や3D可視化を簡単に表示できるコンポーネントです。
基本的には、次のようなソースコードで地図描画が可能になります。
import streamlit as st
import pydeck as pdk
# データを用意
data = [
{"latitude": 35.6895, "longitude": 139.6917, "place": "東京"},
{"latitude": 34.6937, "longitude": 135.5023, "place": "大阪"},
{"latitude": 43.0642, "longitude": 141.3469, "place": "札幌"},
{"latitude": 35.0116, "longitude": 135.7681, "place": "京都"},
{"latitude": 33.5904, "longitude": 130.4017, "place": "福岡"},
]
# レイヤーを設定
layer = pdk.Layer(
"ScatterplotLayer",
data=data,
get_position="[longitude, latitude]",
get_color="[200, 30, 0, 160]",
get_radius=50000,
)
# 初期表示の設定
view_state = pdk.ViewState(
latitude=36.2048,
longitude=138.2529,
zoom=3,
)
# Pydeckチャートを表示
chart = pdk.Deck(
layers=[layer],
initial_view_state=view_state,
map_style=None,
)
st.pydeck_chart(chart)
なぜ嬉しいか?
Streamlit 周りで有名なライブラリとして folium
がありこちらなら柔軟性も高いです。
しかし、Streamlit 公式でこうした操作が行えるコンポーネントは存在しなかったので、「シンプルに実装したいんだけど、選択した点を取るにはサードパーティを入れないといけないな・・・」といったときに有用となります。
また、Snowflake に統合された Streamlit では地図描画として st.map
と st.pydeck_chart
しか使えず、両方とも選択した点の取得ができなかったので、それができるようになるのも嬉しいポイントですね。
ただし、記事公開時点では Streamlit in Snowflake の Streamlit バージョンの最新が 1.35 なので、1.39 の実装までもう少し待つ必要があります。
st.pydeck_chart
で選択した点を取得する
st.pydeck_chart
で選択した点を取得するには、下記のようにレイヤー設定時とコンポーネント呼び出し時にいくつか設定を追加してあげるだけで良いです。
import streamlit as st
import pydeck as pdk
# データを用意
data = [
{"latitude": 35.6895, "longitude": 139.6917, "place": "東京"},
{"latitude": 34.6937, "longitude": 135.5023, "place": "大阪"},
{"latitude": 43.0642, "longitude": 141.3469, "place": "札幌"},
{"latitude": 35.0116, "longitude": 135.7681, "place": "京都"},
{"latitude": 33.5904, "longitude": 130.4017, "place": "福岡"},
]
# レイヤーを設定
layer = pdk.Layer(
"ScatterplotLayer",
data=data,
get_position="[longitude, latitude]",
get_color="[200, 30, 0, 160]",
get_radius=50000,
+ pickable=True,
+ auto_highlight=True,
+ id="map",
)
# 初期表示の設定
view_state = pdk.ViewState(
latitude=36.2048,
longitude=138.2529,
zoom=3,
)
# Pydeckチャートを表示
chart = pdk.Deck(
layers=[layer],
initial_view_state=view_state,
map_style=None,
)
event = st.pydeck_chart(
chart,
+ selection_mode="single-object",
+ on_select="rerun",
)
+event.selection
上記のアプリは次の Playground から操作できます。
st.pydeck_chart
を実行するアプリ
パラメータ解説
- pdk.Layer
- pickable: その名の通り選択可能にするオプションです
- auto_highlight: カーソルが当たっている部分にハイライトをするオプションです
- id: Rerun時に地図描画を一意に固定するIDです(こちらの設定を忘れて、イベント情報更新されず困ったことがありました)
- st.pydeck_chart
- selection_mode: single-object と multi-object を指定でき、言葉の通り、一つを選択できるモードと複数を選択できるモードになります
- on_select: ignore か rerun、コールバック関数を指定でき、選択時にアプリの再描画をするかしないかを指定できます(rerun かコールバック関数を指定した際は、先述の id パラメータを指定する必要があることに注意しましょう!)
おまけ:取得した選択点(辞書型)を Pandas データフレームに変換する
下記のコードを追加することで、辞書型で返却された選択点を Pandas データフレームに変換することができます。最後の "map" は、pdk.Layer の id パラメータに指定した値となります。
import pandas as pd
# オブジェクト部分を取得
objects = event["selection"]["objects"]["map"]
# pandas DataFrameに変換
df = pd.DataFrame(objects)
st.dataframe(df)
上記コードは、st.pydeck_chart
が selection_mode="multi-object"
でもそのまま利用できます。