Snowflake

AIでStreamlitのダッシュボードを標準の部品だけで作る手順|Streamlit in Snowflakeの検証

Ryosuke Ishii

今回は、AIで月次売上ダッシュボードをStreamlit in Snowflakeの標準の部品だけで作りました。HTMLとCSSは1行も書いていません。

お題は「とある町中華」の月次売上を定点観測する1枚です。数字はダミーで、データは弊社のSnowflakeに置きました。手本はPCの1440×900で、寸法、色、文字を指定しています。

作成はAIが担当し、約14分かかりました。手本は先に用意してあったので、この時間は手本を作る時間を含みません。コードは197行です。見やすい1枚にはなりましたが、1画面には収まらず、採点役の2人とも必須条件を不合格としました。

この記事は弊社の検証記録で、StreamlitやSnowflakeの公式手順ではありません。

手本の画面

手本の画面。寸法、色、文字を指定した設計

手本:先に用意した設計の画面(PC 1440×900)。この画面にどこまで近づけるかを測りました。数字はダミーです

完成した画面

標準の部品だけで作った月次売上ダッシュボード

図1:表示域の幅を1440にし、高さを広げて全体を撮った画面。数字はダミーです

月を変える操作は3通りです。プルダウン、前の月・次の月のボタン、月別売上の棒を押す操作で、どれも実際に押して切り替わることを確かめました。プルダウンは3回試して3回とも切り替わりました。

使った部品

場所部品
題名と月の操作`st.columns`、`st.markdown`、`st.button`、`st.selectbox`
KPI 4枚`st.metric`(枠、前月比、推移線)
月別売上`st.altair_chart`(積み上げ棒、棒を押して選ぶ)
曜日×時間`st.altair_chart`(マスと数字)
売れ筋`st.dataframe` の `ProgressColumn`
滞在の長さ別`st.dataframe`、`st.metric`
注記`st.caption`

`st.metric`、`st.dataframe` は、Snowflakeのダッシュボードの例にも出てくる部品です。この例はHTMLもCSSも書いていません。

公式の例と違うところ

部品は標準ですが、アプリの置き方は公式の例と違います。

項目公式の例今回
動かす場所コンテナのランタイムウェアハウスのランタイム
データへのつなぎ方`st.connection(“snowflake”)``get_active_session()`
グラフPlotlyAltair

コンテナのランタイムでは、キャッシュを見る人全員で共有できます。ウェアハウスのランタイムでは、セッションごとです(制限の一覧)。今回はコンテナのランタイムを試していません。

手順1 版を指定して色を決める

`environment.yml` でStreamlitの版を1.52.2に指定しました。色はCSSを書かず、`.streamlit/config.toml` のテーマで決めます。

[theme]
base = "light"
primaryColor = "#3D4070"
backgroundColor = "#F7F9FC"
secondaryBackgroundColor = "#FFFFFF"
textColor = "#1E2430"

ファイルはステージの `.streamlit/` の下に置きました。

手順2 KPIはst.metricに任せる

枠、前月比、推移線が1つの部品で出ます。この記事のコードは要点だけの抜粋です。

st.metric("売上", "207.5万円", delta="-3.9%", border=True,
          chart_data=values, chart_type="line")

`values` は全10か月の値のリストです。前月比の矢印と色は、先頭の半角マイナスで決まるので、手本のU+2212のマイナスは使えませんでした。推移線の色も前月比の色に従うため、月によって赤か灰色になります。選んだ月の点も置けません。

手順3 棒を押して月を変える

Altairの棒グラフに選択を付けます。`on_select` に関数を渡すと、画面を描き直す前に月を変えられます。下の `bars` は月別の表、`on_bar` は選ばれた月を書き込む関数です。

pick = alt.selection_point(name="pick", fields=["MON"], on="click", toggle=False)
chart = alt.Chart(bars).mark_bar(size=40).encode(
    x=alt.X("軸:N", sort=None),
    y=alt.Y("sum(金額):Q", axis=None),
    color="区分:N",
    detail="MON:N",
).add_params(pick)
st.altair_chart(chart, on_select=on_bar, selection_mode="pick", key="bar")

初回は棒を押すと `KeyError: MON` のエラーになり、選択の結果に `MON` が入っていませんでした。`detail=”MON:N”` を足すと動きました。

棒の上の合計は、文字を重ねたグラフだと選択を受け取れないので、月の軸の文字に入れています。そのため合計は棒の下に出ます。

手順4 表はst.dataframeの列の設定で作る

金額と割合の棒は `ProgressColumn` で出します。▼の赤はpandasの `Styler` で付けました。行の高さは `row_height` で詰めています。下の `tbl` は売れ筋の表、`red` は▼に色を付ける関数、`top` は1位の金額です。

st.dataframe(tbl.style.map(red, subset=["前月"]), hide_index=True,
             height=311, row_height=28,
             column_config={"金額(円)": st.column_config.ProgressColumn(
                 format="localized", min_value=0, max_value=top, width=160)})

幅1440で見ると、最初は右の列が切れました。列の幅を数字で指定して直しています。

確かめたこと

全10か月の写真を撮り、KPI、月別売上の合計と営業日、曜日×時間、売れ筋、滞在の長さ別を採点役が正解値と比べました。数字の不一致は0件でした。長い品名は3か所で末尾が切れていて、切れた部分は読めていません。集計のSQLは、別の作り方で全月を確かめたものと同じです。

採点の結果

採点役はAIの2人です。作り手と製品名を伏せ、出来ばえを96点満点、手本の再現度を100点満点で採点しました。

かかった時間必須条件出来ばえ(2人分)再現度(2人分)
約14分2人とも不合格72/6147/47

不合格の理由は2つです。スクロールが要ることと、長い品名が切れることです。品名は列の幅を160pxにした状態でも切れていて、さらに広げる直しは試していません。

時間には、画面を開く許可を人が出すのを待った分と、棒の不具合、表の幅の直しを含みます。

うまくいかないこと

1画面に収まりません

全体の高さが約1170pxになりました。KPIの推移線の高さと表の高さが効いていて、標準の部品だけでは詰めきれません。

Snowsightの外枠の中の表示

図2:Snowsightの外枠の中で開いた画面。下は表示域の外です。数字はダミーです

Snowflakeの画面の外枠の分も差し引かれます。同じ環境で別のアプリを測ったときは、1440×900の窓でアプリに使える表示域は1383×806でした。

座標は指定できません

`st.columns` は比率で並べるので、手本の座標には合いません。差し色の4か所も置けません。

説明の箱はグラフだけです

月別売上と曜日×時間には説明の箱が出ます。表の行には出ません。

月別売上の説明の箱

図3:月別売上の棒に乗せたときの説明の箱。数字はダミーです

まとめ

  • 標準の部品だけで、KPI、グラフ、表、月の切り替えまで約14分で作れました。
  • 色はテーマの設定で決められ、CSSは要りませんでした。
  • 手本の座標どおりの配置と1画面への収まりは、標準の部品では届きませんでした。

関連する記事

ABOUT ME
石井 亮介(りょうさん)
石井 亮介(りょうさん)
データパレード 代表取締役
㈱データパレードの代表取締役で、高田馬場の町中華「一番飯店」のChief Data Officerも務めています。BIツールのセールスエンジニア・システムエンジニア・カスタマーサクセス歴15年。大学のデータサイエンス教育で講師も担当してきました。現在は自社業務のほとんどをAIに移管し、AI10部署と50を超える自動処理が24時間動く「AI経営」を実践中。その実践知をこのブログで発信しています。
記事URLをコピーしました