【Python】地図上にバーグラフを表示するWebアプリ作成【データ解析】

【Python】地図上にバーグラフを表示するWebアプリ作成【データ解析】

地図上にバーグラフを表示する方法をご存知でしょうか?
降水量などを地図上に表現するのにバーグラフを表示するとわかりやすい図が作れたりしますよね。
実はStreamlitというPythonのライブラリを用いると簡単に実現します。

今回は、Streamlitというライブラリを用いて、ブラウザ上で地図とバーグラフを表示するWebアプリを作る方法をご紹介します。

動作検証済み環境

macOS Monterey(12.4), python3.7.10

地図上にバーグラフを表示するWebアプリ

完成物

上のように、大阪のアメダスがある各ポイントにバーグラフを表示させています。 バーグラフは2020年9月~2022年9月の間に50mmの降水量を超えた日数を表しています。 山間部で50mmを超える降水量の日が多かったことがわかりますね。

アプリの作成方法

ソースコード

以下のように、実装します。
以下のコードをmap_plot.py という名前で Desktop/labcode/python/web-data-analysis/map ディレクトリに保存します。

import numpy as np
import pandas as pd
import pydeck as pdk
import streamlit as st

# SETTING PAGE CONFIG TO WIDE MODE AND ADDING A TITLE AND FAVICON
st.title('Osaka Precipitation')

# LOAD DATA ONCE
@st.experimental_singleton
def load_data():
    data = pd.read_csv(
        "./map_data.csv",
        nrows=825,
        names=[
            "lat",
            "lon"
        ],
        skiprows=1, # コメント行をスキップ
        usecols=[2, 3],  # 3、4列目を使用する
    )
    return data


# FUNCTION FOR AIRPORT MAPS
def map(data, lat, lon, zoom):
    st.write(
        pdk.Deck(
            map_style="mapbox://styles/mapbox/light-v8",
            initial_view_state={
                "latitude": lat,
                "longitude": lon,
                "zoom": zoom,
                "pitch": 10,
            },
            layers=[
                pdk.Layer(
                    'HexagonLayer',
                    data=data,
                    get_position='[lon, lat]',
                    radius=750,
                    elevation_scale=4,
                    elevation_range=[0, 5000],
                    pickable=True,
                    extruded=True,
                ),
            ],
        )
    )


# CALCULATE MIDPOINT FOR GIVEN SET OF DATA
@st.experimental_memo
def mpoint(lat, lon):
    return np.average(lat), np.average(lon)


# STREAMLIT APP LAYOUT
data = load_data()

# SETTING THE ZOOM LOCATIONS FOR THE AIRPORTS
zoom_level = 12
midpoint = mpoint(data["lat"], data["lon"])
map(data, midpoint[0], midpoint[1], 8.5)

使用するCSVファイル

図示に使用するCSVファイル map_data.csv は気象庁のサイトからダウンロードしてきたデータを整形したものを使用しています。 データ整形の方法は以前の記事でご紹介していますので、ご確認ください。

map_data.csv の中身は以下のようになっています。 日付と地点名、緯度、経度、降水量の情報が載っています。 実は、地図上にバーグラフを表示する上で最低限必要なデータは実は緯度、経度だけです。Streamlitでは、一行一行を1カウントと見積もってくれるので、同じ緯度・経度の地点を内部で勝手に積算して描画してくれます。

日付と地点名と降水量はグラフの描画には不要ですが、あとでデータを見返したときに何が何か全くわからなくなってしまうので記載しています。このあたりは研究で用いるデータ解析のお作法的なものです。

# 日付, 地点名, 緯度, 経度, 降水量(mm)
2020/9/25,大阪,34.6817,135.5183,64.0
2020/9/25,豊中,34.7833,135.4383,62.0
2020/9/25,能勢,34.9483,135.455,75.0
2020/9/25,茨木,34.86,135.56,56.5
2020/9/25,枚方,34.8083,135.6717,65.5
2020/9/25,生駒山,34.675,135.6767,59.5
2020/9/25,堺,34.555,135.485,52.5
2020/9/25,八尾,34.5967,135.6,53.5
2020/9/25,河内長野,34.4233,135.5433,53.0
2020/9/25,熊取,34.385,135.35,54.0
2020/10/8,河内長野,34.4233,135.5433,57.0
2020/10/9,大阪,34.6817,135.5183,55.5
2020/10/9,生駒山,34.675,135.6767,67.0
2020/10/9,堺,34.555,135.485,62.5
2020/10/9,八尾,34.5967,135.6,53.0
2020/10/9,河内長野,34.4233,135.5433,76.5
2020/10/9,熊取,34.385,135.35,72.0
2020/10/10,生駒山,34.675,135.6767,55.0
2020/10/23,河内長野,34.4233,135.5433,61.0
2020/10/23,熊取,34.385,135.35,50.5
2021/3/21,茨木,34.86,135.56,57.5
2021/3/21,枚方,34.8083,135.6717,50.5
2021/4/17,大阪,34.6817,135.5183,59.5
2021/4/17,枚方,34.8083,135.6717,58.5
2021/4/29,大阪,34.6817,135.5183,105.0
2021/4/29,豊中,34.7833,135.4383,96.5
...

map_data.csv のファイルをご自身のPCの Desktop/labcode/python/web-data-analysis/map フォルダに保存してから、プログラムの実行を試みてください。

streamlitのインストール方法

ライブラリをインターネット上から自身のPCにダウンロードしていないと、 たとえ import streamlit as stと 記述しても使えません。
streamlitがないよ!という旨のエラーが出た場合は、pip installを使ってダウンロードしましょう。実行するディレクトリはどこでもOKです。

$ pip install streamlit 

しばらくして、Successfullyという文言が出て来れば完了です。

プログラムを実行する

ターミナルを開き、

$ cd Desktop/labcode/python/web-data-analysis/map

と入力し、ディレクトリを移動します。あとは以下のコマンドでstreamlitを起動させるだけです。( $マークは無視してください)

$ streamlit run map_plot.py

少しすると自動的にブラウザで http://localhost:8501/ のページが開かれて、上でお見せしたページが表示されると思います。これだけです!

コードの解説

上に書いたソースコードの解説をしていきます。

import numpy as np
import pandas as pd
import pydeck as pdk
import streamlit as st

1行目でstreamlitなどの各種ライブラリをインポートし、ファイル内でライブラリのコマンドを使えるようにします。

# SETTING PAGE CONFIG TO WIDE MODE AND ADDING A TITLE AND FAVICON
st.title('Osaka Precipitation')

Streamlitで作成するWebアプリケーションのタイトルを Osaka Precipitation としています。

# LOAD DATA ONCE
@st.experimental_singleton
def load_data():
    data = pd.read_csv(
        "./map_data.csv",
        nrows=825,
        names=[
            "lat",
            "lon"
        ],
        skiprows=1, # コメント行をスキップ
        usecols=[2, 3],  # 3、4列目を使用する
    )
    return data

load_dataという名前の関数を定義しています。
この関数は、map_data.csvという名前のCSVファイルからデータを読み込み、そのデータをPandasのDataFrame形式で返します。

この関数は、Pandasのread_csvメソッドを使用してCSVファイルからデータを読み込みます。
read_csvメソッドには、いくつかの引数が指定されています。

  • nrows: ファイルから読み込む行数を指定するための引数です。825行だけを読み込むように指定されています。
  • names: CSVファイルのカラム名を指定するための引数です。この例では、”lat”、”lon”という2つの名前が指定されています。
  • skiprows: CSVファイルからスキップする行数を指定するための引数です。この例では、1行目をスキップするように指定されています。
  • usecols: CSVファイルから読み込むカラムを指定するための引数です。この例では、3列目と4列目だけを読み込むように指定されています。

この関数を使用すると、CSVファイルからデータを読み込んでPandasのDataFrame形式で取得することができます。

# FUNCTION FOR AIRPORT MAPS
def map(data, lat, lon, zoom):
    st.write(
        pdk.Deck(
            map_style="mapbox://styles/mapbox/light-v8",
            initial_view_state={
                "latitude": lat,
                "longitude": lon,
                "zoom": zoom,
                "pitch": 10,
            },
            layers=[
                pdk.Layer(
                    'HexagonLayer',
                    data=data,
                    get_position='[lon, lat]',
                    radius=750,
                    elevation_scale=4,
                    elevation_range=[0, 5000],
                    pickable=True,
                    extruded=True,
                ),
            ],
        )
    )

この関数は、大阪の地図を表示するために使用されます。
この関数の引数には、地図上に表示するデータ、経度、緯度、ズーム値が指定されます。
これらの引数を使用して、pdk.Deckを使用して地図を作成し、streamlitを使用してWebページ上に表示します。

地図は、mapbox://styles/mapbox/light-v8というスタイルで作成されます。
また、表示される初期の状態は、引数で指定された経度、緯度、ズーム値に応じて設定されます。

また、この関数は、pdk.Layerを使用して地図上にレイヤーを追加します。
この例では、HexagonLayerというレイヤーが追加されています。
このレイヤーは、データを六角形にプロットするために使用されます。
六角形の大きさや色は、データの値に応じて変化します。

この関数を使用することで、大阪の地図をWebページ上に表示することができます。

# CALCULATE MIDPOINT FOR GIVEN SET OF DATA
@st.experimental_memo
def mpoint(lat, lon):
    return np.average(lat), np.average(lon)

この関数は、指定されたデータセットの緯度と経度の平均値を計算するために使用されます。
この関数は、NumPyのaverage関数を使用して、指定されたデータセットの緯度と経度の平均値を計算します。

この関数を使用することで、データセットの平均値(中点)を計算することができます。
これは、地図の中心を計算するために使用することができます。

# STREAMLIT APP LAYOUT
data = load_data()

# SETTING THE ZOOM LOCATIONS FOR THE AIRPORTS
zoom_level = 12
midpoint = mpoint(data["lat"], data["lon"])
map(data, midpoint[0], midpoint[1], 8.5)

このコードは、Webアプリケーションのレイアウトを定義しています。
まず、load_data関数を使用してCSVファイルからデータを読み込みます。

次に、map関数を使用して地図を作成します。
この関数には、地図上に表示するデータ、中点の緯度、中点の経度、ズーム値が指定されます。
中点は、mpoint関数を使用して計算されます。

最後に、streamlitを使用して作成された地図がWebページ上に表示されます。
このように、このコードは、大阪の地図をWebページ上に表示するためのスクリプトです。

最後に

気象庁の降水量データを整形して、Streamlitを使って地図上にバーグラフを表示してみました。表現方法をいくつも持っていると、研究者、解析者として強みになるのでぜひ一度手を使って試してみてくださいね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です