【Snowflake】ジオハッシュ地図を作ってStreamlitで可視化してみる

【Snowflake】ジオハッシュ地図を作ってStreamlitで可視化してみる | Tableau-id Press -タブロイド-
snowflake-logo-1200x630-960x504

こんにちは。ozawaです!

今日は、ジオハッシュ地図をStreamlit in Snowflakeで表示してみようと思います。

ジオハッシュ地図ではOOkm×OOkmの色付きタイルを地図上に並べて表示できます。(この後詳しく説明します)

緯度経度+数値データのレコードを、タイルごとにレコードを集計することで、表示を軽くすることができるうえに、どのエリアが多い・少ないのかがパッと見てわかるようになります。

(ちなみに筆者はジオハッシュ地図が非常に好きで、20年くらいまえのポケモンの戦闘に入るときのグラフィックを想起させます。わかる方います?)

 

本ブログはポリゴン地図を表示する手法と近い部分があるので、合わせてこちらのブログもどうぞ!

【Snowflake】Streamlit in Snowflakeでポリゴン地図を表示

 

ジオハッシュの説明

ジオハッシュは緯度経度といった地理座標を「ABA…」のような文字列に変換する処理になります。

ジオハッシュ文字に対して、地理領域が設定されており、そこに含まれる緯度経度がそのジオハッシュ文字に変換されます。

つまり、各緯度経度とジオハッシュ文字は多対1であり、緯度経度のプロットをジオハッシュで集計できます。

また、ジオハッシュからジオハッシュの代表ポイントやポリゴンを出力できます。

 

Snowflakeでは、ジオハッシュ化や、ジオハッシュからポリゴンやポイント生成の関数が用意されています。

ST_GEOHASH:緯度経度をジオハッシュ化

ST_GEOGFROMGEOHASHST_GEOMFROMGEOHASH:ジオハッシュからポリゴン領域を生成

ST_GEOGPOINTFROMGEOHASHST_GEOMPOINTFROMGEOHASH:ジオハッシュからポイントを生成

 

今回のデモでは、緯度経度→ジオハッシュ化→ポリゴン領域を生成 することで、日本を四角いタイルで覆った地図を生成していきます。

 

実装!!

今回は、ジオハッシュで作成したタイル地図をStreamlitで表示します。タイルの中に市区町村の代表点がどれだけ入っているかで色分けをしていきます。

データソースはPODB市区町村データを使っていきます。

まずはソースコードを添付します。

# 必要なライブラリをインポート
import geopandas as gpd
from shapely.geometry import shape
from shapely.validation import make_valid
import json
import streamlit as st
import pydeck as pdk
from snowflake.snowpark.context import get_active_session

# Snowflakeからデータを取得する関数をキャッシュ化
@st.cache_resource
def create_source():
    session = get_active_session()
    # Snowflakeからデータをクエリして取得
    df = session.sql('''
SELECT
    CITY_NAME
    ,ST_GEOHASH(ST_MAKEPOINT(LONGITUDE, LATITUDE), 5) AS GEO_HASH //緯度経度からジオハッシュ化
    ,ST_GEOMFROMGEOHASH(GEO_HASH) AS REVERSE_GEO_HASH //ジオハッシュからGeometry型のポリゴンタイルを作成
FROM
    PREPPER_OPEN_DATA_BANK__JAPANESE_CITY_DATA.E_PODB.E_CI_FD20
    ''').to_pandas()
    return df

# データの取得と加工
df = create_source()
st.write(df[:100])

# ジオハッシュタイルごとに市区町村代表点が
df = df.groupby(['GEO_HASH', 'REVERSE_GEO_HASH'])['CITY_NAME'].count().reset_index().rename(columns={'CITY_NAME': 'CNT_CITY'})
st.write(df)

# ジオメトリポリゴンを使える形に修正
def trans_shape(x):
    geometry = shape(json.loads(x))
    if geometry.is_valid:
        return geometry
    else:
        st.write(x)
        return make_valid(geometry)

# データの可視化(map)
geometry = [trans_shape(row) for row in df['REVERSE_GEO_HASH'] ]
# st.write(df['REVERSE_GEO_HASH'].tolist')
gdf = gpd.GeoDataFrame(df[['CNT_CITY']].reset_index(), geometry=geometry)
gdf["color"] = [[i*255, (1-i)*255, 0, 140] for i in gdf['CNT_CITY'].fillna(0)/gdf['CNT_CITY'].max()]

layer = pdk.Layer(
    "GeoJsonLayer",
    data=gdf,
    get_polygon="geometry",
    get_fill_color='color',  # ポリゴンの塗りつぶし色
)

fig = pdk.Deck(
        layers=[layer],
        map_style="mapbox://styles/mapbox/light-v9",
        initial_view_state=pdk.ViewState(
            latitude=35.5,
            longitude=139.5,
            zoom=8,
            pitch=0
        )
)

# #タイトル
st.title('ジオハッシュ地図を表示できたよ~')
st.write('ジオハッシュ領域ごとの市区町村数を表示')

# #地図表示
st.pydeck_chart(fig)

実行結果

タイル形式のポリゴンが表示され、領域に含まれる市区町村の代表点の数に応じて色分けできました~!!

 

ポイント1:ジオハッシュを作成

ST_GEOHASHを使って、緯度経度のポイントからジオハッシュを作成します。

ST_GEOHASH(ST_MAKEPOINT(LONGITUDE, LATITUDE), 5) AS GEO_HASH

今回関数の第2引数に指定されている「5」はジオハッシュの文字数になります。文字数が大きいほどジオハッシュから生成されるタイルは細かくなり、文字数が少ないほどタイルは荒くなります。

ちなみに文字数「5」のジオハッシュ地図は日本の市区町村・町丁目単位の集計を行うのにちょうどいいサイズです。

ポイント2:ジオハッシュからタイルポリゴンを作成

作成した5文字のジオハッシュからタイルポリゴンを作成していきます。

ST_GEOMFROMGEOHASH(GEO_HASH) AS REVERSE_GEO_HASH

これを実行すると、GEO_HASHに対応するタイルポリゴンが作成されます。

 

ちなみにタイルポリゴンREVERSE_GEO_HASHの中身を見てみると、、、

ポイントが4つのポリゴンが作成されており、長方形の形状をしていそうなのが分かります。

"{ ""coordinates"":
 [ [
  [ 1.325390625000000e+02, 3.423339843750000e+01 ],
  [ 1.325390625000000e+02, 3.427734375000000e+01 ],
  [ 1.325830078125000e+02, 3.427734375000000e+01 ],
  [ 1.325830078125000e+02, 3.423339843750000e+01 ],
  [ 1.325390625000000e+02, 3.423339843750000e+01 ]
 ] ],
""type"": ""Polygon"" }"

おわりに

今回使用したPrepper Open Data Bankは、都道府県データ・ポリゴンだけではなく、カレンダーデータや、気象予報データ等があります。ぜひお使いください。

truestarでは、Streamlit画面開発だけではなく、Snowflake導入検討、導入支援や環境構築まで幅広くサポート可能です。

Snowflakeに゙興味がある、導入済みだけどもっとうまく活用したい等々ありましたら、ぜひこちらから相談ください!

これまでのSnowflakeに関する記事はこちら