Published on

stliteでインフルエンザの発生状況をサーバーレスで伝えたい

Authors
  • avatar
    Name
    Nomad Dev Life
    Twitter
2025-01-04-title

インフルエンザの発生状況をサーバーレスで伝えたい

ここに来て、インフルエンザが猛威をふるっているようです。インフルに罹患した、というポストを年末に目にすることもありました。

12月27日の発生状況のレポートを見ると、報告数はまたかなり増えています。この記事の最後にレポートのリンクを貼っておくので、気になる方は見てください。

Streamlitとstlite

前回は、Google Colabを使ってインフルエンザの発生状況をグラフにしました。今回は、stliteというwasmのツールを使ってグラフを表示します。

stliteは、Streamlitをブラウザ上で実行できるようにする技術です。StreamlitはサーバーにdeployするWebアプリケーションですが、stliteはwasmを利用してPythonのインタープリターをブラウザ上で動かし、Streamlitアプリケーションを完全にクライアントサイドで実行します。

Streamlitは、Pythonのみでデータ可視化や機械学習モデルのデモなど、インタラクティブなWebアプリケーションを簡単に作成するためのフレームワークです。少ないコード量で、インタラクティブなレポートを作成することができます。 StreamlitはPandasのDataframeをデータソースとしてレポートを生成します。Streamlitでどのようなことができるかは、以下のページを見てください。

データソース

前回、厚生労働省が週次で発行している"インフルエンザの発生状況"からインフルエンザの報告数を抜き出し、レポートを生成しました。あの時に抽出したデータをdf.to_csvでCSVファイルに出力し、Webサーバー上に配置しました。今回はこのファイルがデータソースになります。

stliteをlocalで試す場合、このようにWebサーバーにアップロードしたファイルをダウンロードする際に、CORSに引っかかることがあります。その場合はWebサーバー側のレスポンスヘッダに"Access-Control-Allow-Origin: *"を付与すると良いでしょう。

stlite

stliteはすでにCDNに配置されている為、開発環境を構築する必要はありません。HTMLファイルを作成し、stlite.jsのパスをHTMLに記載します。イメージはこんなカンジです。

flu-stlite

HTMLは以下です。

<html>
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <title>都道府県別 インフルエンザ報告数 週次積み上げ</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/@stlite/mountable@0.58.3/build/stlite.css"
    />
  </head>
  <body>
    <div id="root"></div>
    <script src="https://cdn.jsdelivr.net/npm/@stlite/mountable@0.58.3/build/stlite.js"></script>
    <script>
      stlite.mount(
        {
          requirements: ["pandas"],
          entrypoint: "streamlit_app.py",
          files: {
            "streamlit_app.py": `
import streamlit as st
import pandas as pd
import altair as alt

st.title('都道府県別 インフルエンザ報告数 週次積み上げ')

# FeatherファイルをダウンロードしてDataFrameを作成
df = pd.read_csv('https://nomad-dev-life.net/static/data/2025-01-03/flu-20241227.csv')

st.write(alt.Chart(df).mark_bar().encode(
    x=alt.X('pref', sort=['北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県', '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県', '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県', '岐阜県', '静岡県', '愛知県', '三重県', '滋賀県', '京都府', '大阪府', '兵庫県', '奈良県', '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県', '徳島県', '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県', '熊本県', '大分県', '宮崎県', '鹿児島県', '沖縄県'] ),
    y='reported',
    color='date',
    order=alt.Order(
      'date',
      sort='ascending'
    )
))
`,
          },
        },
        document.getElementById("root")
      );
    </script>
  </body>
</html>

requirementsには、Pythonでrequirements.txtに書くのと同じように、使用するモジュールを記載します。ただ、自分が使いたいモジュールが必ずしも使えるとは限りません。試しにpyarrowを指定してみたところ、以下のようなエラーが出ました。

Traceback (most recent call last):
  File "/lib/python3.12/site-packages/micropip/_commands/install.py", line 146, in install
    raise ValueError(
ValueError: Can't find a pure Python 3 wheel for: 'pyarrow'
See: https://pyodide.org/en/stable/usage/faq.html#why-can-t-micropip-find-a-pure-python-wheel-for-a-package

最後の一文に記載されているFAQのページを見ると、パッケージにバイナリ拡張 (C、Fortran、Rust など) がある場合は、Pyodide でパッケージ化する必要があるらしく、pyarrowは現時点でPyodideでパッケージ化されていないのかもしれません。(ですので、今回はCSVファイルで試しました)

filesの箇所を見てもらえれば分かるように、データソースとなるDataframeを取得してグラフ等を表示するという、Streamlitのコードの書き方と全く同じです。都道府県順に並べるのと、bar chartに週次ごとの報告数を積み上げる際に最近の数値が上に来るようにsortを調整していますが、それを除くとシンプルなコードになっています。

このflu_2024.htmlもWebサーバーに置きました。stliteでどのように表示されるか、試してみてください。

おわりに

stliteを使用することで、HTMLを用意すれば、レポートをユーザーに見せることができます。サーバーを用意しなくて良いのは助かります。

Google Colabだと、gistに貼ったやつを各自で動かしてもらう必要があり、ちょっと手間だな、と思っていたので、ブログ記事を書く側としてもこういった技術は助かります。