シェルスクリプトマガジン

特集1 Streamlitで作るデータ分析Webアプリ(Vol.93記載)

著者:邑川 真也

「Streamlit」は、OSS(オープンソースソフトウエア)のPython向けフレームワーク(ライブラリ)です。データの可視化機能や分析機能、ダッシュボードなどを備えるWebアプリケーションを、Pythonを使って迅速かつ容易に作成できます。本特集では、さまざまなWebアプリケーションを実際に作成しながら、基本的なデータの可視化方法から、ノーコードでデータ分析を実現する方法まで、Streamlitのさまざまな活用方法を紹介します。

シェルスクリプトマガジン Vol.93は以下のリンク先でご購入できます。

図2 HTMLとCSS、JavaScriptを用いて棒グラフを描くコードの例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0">
  <title>Bar Chart Example</title>
  <style>
    .chart-container {
      width: 70%;
      margin: 0 auto;
    }
  </style>
</head>
<body>
  <div class="chart-container">
    <canvas id="myBarChart"></canvas>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <script>
    var ctx = document.getElementById('myBarChart').getContext('2d');
    var myBarChart = new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['January', 'February', 'March',
                 'April', 'May', 'June', 'July'],
        datasets: [{
          label: 'Sample Data',
          data: [65, 59, 80, 81, 56, 55, 40],
          backgroundColor: 'rgba(54, 162, 235, 0.2)',
          borderColor: 'rgba(54, 162, 235, 1)',
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          y: {
            beginAtZero: true
          }
        }
      }
    });
  </script>
</body>
</html>

図3 Streamlitを用いて棒グラフを描くコードの例

import streamlit as st
import pandas as pd
import altair as alt

data = pd.DataFrame({
    'Month': ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
    'Value': [65, 59, 80, 81, 56, 55, 40]
})
chart = alt.Chart(data).mark_bar().encode(
    x='Month',
    y='Value',
    color=alt.value('steelblue')
)
st.title('Bar Chart Example')
st.altair_chart(chart, use_container_width=True)

図6 シンプルなWebアプリケーションのコード

import streamlit as st

# タイトルを表示
st.title("シェルスクリプトマガジン")

図9 架空の株価データを生成して表示するコード

import streamlit as st
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# 株価データを生成(仮のデータ)
dates = [datetime.today() - timedelta(days=i) for i in range(14)]
dates.reverse()
data = {
  'Date': dates,
  'Google': np.random.uniform(2700, 3000, 14),
  'Apple': np.random.uniform(140, 160, 14),
  'Meta': np.random.uniform(320, 350, 14),
  'Amazon': np.random.uniform(3300, 3500, 14)
}
# データフレームに変換
df = pd.DataFrame(data)
df.set_index('Date', inplace=True)
# タイトルを表示
st.title("株価データの可視化")
# データフレームの表示
st.dataframe(df)

図14 「data.csv」ファイルに記述するデータ(抜粋)

Case ID,Company,Inquiry Summary,Status,Start Date,Severity
1,Acme Corp,大規模データセットに対するクエリの最適化について,Open,2024-05-19,Sev4
2,Globex Inc,DWHのベストプラクティスについて,Open,2024-05-26,Sev3
3,Globex Inc,データロード時のエラー,Open,2024-05-21,Sev3
4,Soylent Corp,新機能の有効化について,Open,2024-05-22,Sev2
5,Soylent Corp,レプリケートに失敗しています,Open,2024-05-22,Sev3
(略)

図15 ダッシュボードアプリのコード

import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# ページ設定
st.set_page_config(
  page_title="サポートデスクダッシュボード",
  initial_sidebar_state="expanded",
  layout="wide"
)
st.title("サポートデスクダッシュボード")
# チケット一覧を表示
st.subheader("チケット一覧")
# データ読み込み
df = pd.read_csv("data.csv")

with st.container(border=True, height=100):
  filter1, filter2 = st.columns(2)
with filter1:
  # ステータスによるフィルタ
  status_list = df['Status'].unique()
  selected_status = st.multiselect("ステータス",
                                   options=status_list,
                                   default=status_list)
with filter2:
  # 重要度によるフィルタ
  severity_list = df['Severity'].unique()
  selected_severity = st.multiselect("重要度",
                                     options=severity_list,
                                     default=severity_list)
# フィルタを適用
if selected_status or selected_severity:
  df = df[(df['Status'].isin(selected_status) &
           df['Severity'].isin(selected_severity))]

# データを表示
st.dataframe(df, use_container_width=True)
# グラフを横並びに表示するレイアウトを作成
st.markdown("")
col1, col2  = st.columns(2)
# 縦棒グラフでステータスの数を表示
with col1:
  st.subheader("チケットごとのステータス集計")
  fig, ax = plt.subplots()
  status_counts = df["Status"].value_counts()
  ax.bar(status_counts.index, status_counts.values,
         color="skyblue")
  ax.set_xlabel("Status")
  ax.set_ylabel("Count")
  ax.set_title("Tickets by Status")
  with st.container(border=True):
    st.pyplot(fig)
# 縦棒グラフで重要度の数を表示
with col2:
  st.subheader("チケットごとの重要度集計")
  severity_counts = df["Severity"].value_counts()
  fig, ax = plt.subplots()
  ax.bar(severity_counts.index, severity_counts.values, color="coral")
  ax.set_xlabel("Severity")
  ax.set_ylabel("Count")
  ax.set_title("Tickets by Severity")
  with st.container(border=True):
    st.pyplot(fig)

# CSVダウンロード
csv = df.to_csv(index=False)
st.download_button(
  label="Download CSV",
  data=csv,
  file_name='sample_data.csv',
  mime='text/csv'
)

図17 「config.toml」ファイルに記述するテーマ設定の例

[theme]
primaryColor = "#F14143"              # プライマリカラー
backgroundColor = "#101216"           # 背景色
secondaryBackgroundColor = "#191B20"  # セカンダリ背景色
textColor = "#F9F9F9"                 # テキストカラー
font = "sans serif"                   # フォント

図18 「pygw_test.py」ファイルに記述するコード

from pygwalker.api.streamlit import StreamlitRenderer
import pandas as pd
import streamlit as st

# Streamlitの画面幅を調整
st.set_page_config(
  page_title="Use Pygwalker In Streamlit",
  layout="wide"
)
# データの取得
df = pd.read_csv("https://kanaries-app.s3.ap-northeast-1.amazonaws.com/public-datasets/bike_sharing_dc.csv")
# PYGWalkerによる可視化 
pyg_app = StreamlitRenderer(df)
pyg_app.explorer()