SASデータを解析するアプリをstreamlitで作ってみる

1.9K Views

April 15, 25

スライド概要

[第11回大阪sas勉強会]

profile-image

SAS言語を中心として,解析業務担当者・プログラマなのコミュニティを活性化したいです

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

第 11 回大阪 SAS 勉強会 「 SAS データを解析する」アプリを streamlit で作ってみる 武田薬品工業株式会社 舟尾 暢男 資料中のプログラム: https://nfunao.web.fc2.com/files/python_intro2_06.zip 1

2.

メニュー • インストール • アプリの作成 → 実行 → 終了 • 「 SAS データを解析するアプリ」を streamlit で作成 • 各種出力と widget • session_state • レイアウト • その他 2

3.

python と streamlit のインストール • python と Anaconda をインストール https://www.python.org/ https://www.anaconda.com/download • Anaconda Prompt 等で、モジュールをいくつかインストール pip install streamlit pip install pandas pip install matplotlib • インストールできたか確認 streamlit hello • PC SAS は既に入っている前提(SAS v9.4) 3

4.

メニュー • インストール • アプリの作成 → 実行 → 終了 • 「 SAS データを解析するアプリ」を streamlit で作成 • 各種出力と widget • session_state • レイアウト • その他 4

5.

1. PC 上でのアプリの作成 → 実行 → 終了 • アプリを作成 → C:\temp に app.py というテキストファイルにて保存 import streamlit as st st.title('Sample App.') • Anaconda Prompt 等で、アプリのファイル(app.py)の階層まで移動後、実行 • 【コマンドプロンプト】目的別コマンド一覧: https://techmania.jp/blog/cmd0002/ cd c:\temp streamlit run app.py streamlit 用のコマンド streamlit --help streamlit --version streamlit hello streamlit docs streamlit config show streamlit cache clear 5

6.

1. PC 上でのアプリの作成 → 実行 → 終了 • C:\temp\app.py import streamlit as st st.title('Sample App.') たった 2 行の命令でブラウザが立ち上がりアプリが完成! 【言い忘れ】 • 2025 年 1 月のナニワデータサイエンス研究会にて R shiny アプリの講演後、森岡さんより 「 SAS で、この様なアプリを作成する方法はないのでしょうか?」とご質問いただく 1. 2. 3. • R shiny python shiny python streamlit 回答: python の streamlit を使うことで、簡単なアプリを作成することが出来るので、 SAS データを解析するアプリを streamlit で作ってみました。 6

7.

1. PC 上でのアプリの作成 → 実行 → 終了 • アプリの右上の Settings より [Run on save] をチェック • プログラムが修正・保存されると自動で更新される • 自動更新しない場合、コマンド上でアプリを 【終了⇒起動】 しなければいけなくなり、非常に面倒 • 終了する場合は、 Anaconda Prompt 上で [Ctrl] + [C] • アプリ作成時は以下を参照しつつ作業すると楽? • Streamlit Magic Cheat Sheets https://cheat-sheets.streamlit.app/ • Streamlit documentation https://docs.streamlit.io/ 7

8.

メニュー • インストール • アプリの作成 → 実行 → 終了 • 「 SAS データを解析するアプリ」を streamlit で作成 • 各種出力と widget • session_state • レイアウト • その他 8

9.
[beta]
2. SAS プログラムを実行
•

C:\temp\app.py → 黄色マーカーがバッチ実行部分
import streamlit as st
import subprocess
subprocess.Popen(r'"C:\Program Files\SAS_9.4\SASFoundation\9.4\sas.exe" -sysin
"C:\temp\sample.sas" -log "C:\temp" -print "C:\temp" -nosplash -icon',
shell=True)

•

C:\temp\sample.sas
data x
; x=1 ;
proc print ; run ;

•

Anaconda Prompt 等でアプリ(app.py)を起動 → 結果とログファイルが出力
SAS システム
OBS
1

x
1

9

10.

3. SAS データの読み込み&解析 • C:\temp\app.py → 黄色マーカーが SAS ファイルの読み込み部分 import streamlit as st import pandas as pd import matplotlib.pyplot as plt st.title("Upload a SAS and Analyze Data") uploaded_file = st.file_uploader("Choose a SAS file", type="sas7bdat") if uploaded_file is not None: df = pd.read_sas(uploaded_file, format='sas7bdat', encoding='cp932') st.write("DataFrame Preview:") st.write(df.head(7)) vars = [c for c in df.columns] value = st.selectbox("Variable", vars) summary_stats = df[value].describe() st.subheader("Summary Statistics") st.write(summary_stats) st.subheader("Histogram") fig, ax = plt.subplots(1, 1, figsize=(10, 5)) ax.hist(df[value], bins=20, alpha=0.7, color='blue', edgecolor='black') plt.tight_layout() st.pyplot(fig) 10

11.

3. SAS データの読み込み&解析 データ表示や解析は python にて実施 11

12.

4. 例数設計アプリ C:\temp ① 生成 app.py ② 実行 parameters.sas (各パラメータ) _EXE.sas (実行ファイル) samplesize.sas (例数設計部分) • • ③ 出力 result.html C:\temp に _EXE.sas(実行ファイル)と samplesize.sas(例数設計部分の SAS )を保存 ( python から自動作成したり、サブフォルダに入れておいても良いが簡単のため) app.py から parameters.sas(例数設計の各パラメータを設定したマクロ変数定義部分)を 作成後、 _EXE.sas を実行する 12

13.

4. 例数設計アプリ • C:\temp\_EXE.sas options source source2 symbolgen ; %let _path = C:/temp ; %inc "./parameters.sas" ; %inc "./samplesize.sas" ; • C:\temp\samplesize.sas ods html file='result.html' path="&_path" style=styles.sasweb ; proc power; twosamplemeans test = diff meandiff = &_meandiff. stddev = &_stddev. alpha = &_alpha. power = &_power. ntotal = . ; run ; ods html close; x "&_path\result.html" ; • • C:\temp に _EXE.sas(実行ファイル)と samplesize.sas(例数設計部分の SAS )を保存 ( python から自動作成したり、サブフォルダに入れておいても良いが簡単のため) app.py から parameters.sas(例数設計の各パラメータを設定したマクロ変数定義部分)を 作成後、 _EXE.sas を実行する 13

14.
[beta]
4. 例数設計アプリ
•

C:\temp\app.py → まず parameters.sas を作成後、_EXE.sas を実行し例数設計
import streamlit as st
import subprocess
st.title("Sample Size - 2-sample t-test")
meandiff = st.number_input('Meandiff:', 1)
stddev
= st.number_input('Stddev:',
2)
alpha
= st.number_input('Alpha:', 0.05)
power
= st.number_input('Power:', 0.8)
if st.button("Save Parameters"):
with open("C:/temp/parameters.sas", "w") as f:
f.write("%let _meandiff = " + str(meandiff) +" ; ")
f.write("%let _stddev
= " + str(stddev ) +" ; ")
f.write("%let _alpha
= " + str(alpha
) +" ; ")
f.write("%let _power
= " + str(power
) +" ; ")
st.success(f"Parameters has been saved.")
if st.button("Calculate"):
subprocess.Popen(r'"C:\Program Files\SAS_9.4\SASFoundation\9.4\sas.exe" sysin "C:\temp\_EXE.sas" -nosplash -icon', shell=True)
14

15.

4. 例数設計アプリ 15

16.

5. SAS データを解析するアプリ C:\temp ① 生成 app.py ② 実行 parameters.sas (各パラメータ) _RUN.sas (実行ファイル) summary.sas (データ要約部分) • • ③ 出力 result.html C:\temp に _RUN.sas(実行ファイル)と summary.sas(データを要約する部分の SAS )を保存 ( python から自動作成したり、サブフォルダに入れておいても良いが簡単のため) app.py からデータを読み込んだ後、parameters.sas(データ名と変数名を設定した マクロ変数定義部分)を作成、最後に _RUN.sas を実行する 16

17.

5. SAS データを解析するアプリ • C:\temp\_RUN.sas options source source2 symbolgen ; %let _path = C:/temp ; %inc "./parameters.sas" ; %inc "./summary.sas" ; • C:\temp\summary.sas libname IN "&_path" ; ods html file='result.html' path="&_path" style=styles.sasweb ; proc means data=IN.&_data. n mean stddev min q1 median q3 max ; var &_var. ; run ; proc sgplot data=IN.&_data. ; histogram &_var. / scale=count ; density &_var. / type=normal ; run; ods html close; x "&_path\result.html" ; • • C:\temp に _RUN.sas(実行ファイル)と summary.sas(データを要約する部分の SAS )を保存 ( python から自動作成したり、サブフォルダに入れておいても良いが簡単のため) app.py からデータを読み込んだ後、parameters.sas(データ名と変数名を設定した マクロ変数定義部分)を作成、最後に _RUN.sas を実行する 17

18.
[beta]
5. SAS データを解析するアプリ
•

C:\temp\app.py → まず parameters.sas を作成後、_RUN.sas を実行しデータ解析
import streamlit as st
import pandas
as pd
import subprocess
st.title("Upload a SAS and Analyze Data")
uploaded_file = st.file_uploader("Choose a SAS file", type="sas7bdat")
if uploaded_file is not None:
df = pd.read_sas(uploaded_file, format='sas7bdat', encoding='cp932')
filename = uploaded_file.name.replace('.sas7bdat', '')
st.write("DataFrame Preview:")
st.write(df.head(7))
vars = [c for c in df.columns]
var = st.selectbox("Variable", vars)
with open("C:/temp/parameters.sas", "w") as f:
f.write("%let _data = " + filename + " ; ")
f.write("%let _var = " + var
+ " ; ")
st.success(f"Parameters has been saved.")
if st.button("Run"):
subprocess.Popen(r'"C:\Program Files\SAS_9.4\SASFoundation\9.4\sas.exe" sysin "C:\temp\_RUN.sas" -nosplash -icon', shell=True)
18

19.

5. SAS データを解析するアプリ 19

20.

おまけ: アプリをデスクトップアプリ化 • Streamlit アプリを簡単にデスクトップアプリ化するコマンドを作った https://zenn.dev/ohtaman/articles/streamlit-desktop-app • Anaconda Prompt 等で、モジュールをいくつかインストール pip install streamlit-desktop-app pip install easygui • その他の方法: Streamlit の EXE 化 https://qiita.com/Gyutan/items/c158920f0693fb099e92 20

21.

おまけ: アプリをデスクトップアプリ化 app2.exe _internal app.py _RUN.sas summary.sas parameters.sas ・・・ 21

22.

おまけ: アプリをデスクトップアプリ化 • C:\temp\app.py をデスクトップアプリ化 → C:\temp\dist\app\app2.exe が作成される streamlit-desktop-app build app.py --name "app2" • app2.exe と _internal フォルダ (依存ライブラリ等が格納)が作成される • 容量は大きめです…( 1 GB 以上) • app.py (次頁、メインの python プログラム)は _internal フォルダに格納されるので、ここが カレントディレクトリとなる • app2.exe app2.exe 作成後、_RUN.sas と summary.sas を _internal フォルダに手動で格納して完成 app.py _RUN.sas summary.sas parameters.sas ・・・ • 配布の際は _internal を含めて zip 等に圧縮 • parameter.sas はアプリ(app.py)実行時に自動作成される • 結果の html ファイルは解析用データと同じ階層に作成 (もちろん本仕様は変更可能) _internal 22

23.
[beta]
おまけ: アプリをデスクトップアプリ化
•

C:\temp\app.py

import streamlit as st
import pandas
as pd
import subprocess
import easygui
import os

if "is_button" not in st.session_state:
st.session_state["is_button"]
= False
if "uploaded_file" not in st.session_state:
st.session_state["uploaded_file"] = ""
def get_local_file_path():
file_path = easygui.fileopenbox()
return file_path
os.chdir(os.path.dirname(os.path.abspath(__file__)))
st.title("Upload a SAS and Analyze Data")
if st.button("Choose a SAS file"):
st.session_state["is_button"]
= True
st.session_state["uploaded_file"] = get_local_file_path()
if st.session_state["is_button"]:
file_path
= st.session_state["uploaded_file"]
_, extension = os.path.splitext(file_path)
if extension.lower() == ".sas7bdat":
folder_name = os.path.dirname(file_path)
file_name
= os.path.basename(file_path).replace('.sas7bdat', '')
df = pd.read_sas(file_path, format='sas7bdat', encoding='cp932')
st.write("DataFrame Preview:")
st.write(df.head(7))
vars = [c for c in df.columns]
var = st.selectbox("Variable", vars)

with open("parameters.sas", "w") as f:
f.write("%let _path = " + folder_name + " ; ")
f.write("%let _data = " + file_name
+ " ; ")
f.write("%let _var = " + var
+ " ; ")
st.success(f"Parameters has been saved.")
else:
st.write("This file is NOT a SAS file.")
if st.button("Run") and st.session_state["is_button"]:
sas_exe = r'"C:\Program Files\SAS_9.4\SASFoundation\9.4\sas.exe"'
sas_run = r'_RUN.sas'
command = f' {sas_exe} -sysin "{sas_run}" -nosplash -icon'
subprocess.Popen(command, shell=True)

•

os.chdir() でカレントディレクトリを _internal に移動
•

•

streamlit のモジュールは、セキュリティの観点で
ローカルファイルへのアクセスを制限している
•

•

_RUN.sas と parameter.sas のパスについて明示的
に処理する必要がなくなる

緑の部分にて別機能で SAS ファイルの情報を取得

streamlit では session_state という概念がある
•
•

赤の部分にて処理
session_state は後ろのスライドにて言及
23

24.

おまけ: アプリをデスクトップアプリ化 • C:\temp\_RUN.sas options source source2 symbolgen ; %inc "./parameters.sas" ; %inc "./summary.sas" ; • C:\temp\summary.sas libname IN "&_path" ; ods html file='result.html' path="&_path" style=styles.sasweb ; proc means data=IN.&_data. n mean stddev min q1 median q3 max ; var &_var. ; run ; proc sgplot data=IN.&_data. ; histogram &_var. / scale=count ; density &_var. / type=normal ; run; ods html close; x """&_path\result.html"""; 24

25.

お遊び: Gemini に SAS データを解析させるアプリ 注:機密データ を入力しないで 下さい! 【事前準備】 • Gemini にログイン( Google アカウントがあればすんなり)、当方は無料版を試用 https://gemini.google.com/app?hl=ja • Gemini API を使用するための API キーを取得 参考: https://monomonotech.jp/kurage/memo/m240725_get_gemini_api_key.html • C:\temp に .env というテキストファイルを作成し、以下を書き込む ( XXXXX は、ご自身の Gemini API キー) GOOGLE_API_KEY=XXXXXX • Anaconda Prompt 等で、モジュール google-generativeai と dotenv を入れる pip install google-generativeai python-dotenv 25

26.

お遊び: Gemini に SAS データを解析させるアプリ ・・・ ① SASデータ の読み込み 注:機密データ を入力しないで 下さい! ③ 補足説明も表示 ④ [Analyze] で、 生成されたSAS プログラムを実行 ② 選択した変数 に関する解析 プログラムを Genemiが生成 (ファイルも生成) 結果と Gemini に よる要約が出力 結果はお楽しみ… ? 26

27.
[beta]
お遊び:
•

Gemini に SAS データを解析させるアプリ

if sas_code_start != -1 and sas_code_end != -1:
sas_program = response.text[sas_code_start +
len("```sas"):sas_code_end].strip()
try:
with open(r"C:/temp/program.sas", "w") as file:
file.write(sas_program)
st.success(f"SAS program could be extracted from
the response.")
except Exception as e:
st.error(f"Error: {e}")
else:
st.write("SAS program could not be extracted from
the response.")

C:\temp\app.py

import streamlit as st
import pandas
as pd
import subprocess
import codecs
import time
import os
import google.generativeai as genai
from
dotenv import load_dotenv
st.title("Upload a SAS and Analyze Data")
uploaded_file = st.file_uploader("Choose a SAS file", type="sas7bdat")

if st.button("Analyze"):
subprocess.Popen(r'"C:\Program
Files\SAS_9.4\SASFoundation\9.4\sas.exe" -sysin
"C:\temp\program.sas" -nosplash -icon', shell=True)
time.sleep(10)
try:
with codecs.open(r"C:/temp/result.html", 'r', 'cp932') as file:
html_content = file.read()
summary_query = (
"Summarize the following content of an HTML report. "
"Provide the main insights and conclusions:\n" + html_content
)
summary_response = chat.send_message(summary_query)
st.subheader("Summary of SAS Results:")
st.write(summary_response.text)
subprocess.Popen(["start", "C:/temp/result.html"], shell=True)
except Exception as e:
st.error(f"Error reading or summarizing result.html: {e}")

if uploaded_file is not None:
df = pd.read_sas(uploaded_file, format='sas7bdat', encoding='cp932')
filename = uploaded_file.name.replace('.sas7bdat', '')
st.write("DataFrame Preview:")
st.write(df.head(7))
vars = [c for c in df.columns]
var = st.selectbox("Variable", vars)
load_dotenv()
GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY')
genai.configure(api_key=GOOGLE_API_KEY)
model = genai.GenerativeModel('gemini-2.0-flash')
chat = model.start_chat()
query = "generate SAS program to analyze the variable " + var + " in
SAS dataset " + uploaded_file.name + " read by this app, and generate
summary statistics and graphs, and then output result.html, using the
path C:\\temp as libname."
response = chat.send_message(query)
st.write("Gemini, " + query)
st.write(response.text)
sas_code_start = response.text.find("```sas")
sas_code_end
= response.text.find("```", sas_code_start +
len("```sas"))

注:機密データ
を入力しないで
下さい!

•
•

赤字部分で Genemi を呼び出し
青字部分で Genemi が SAS や要約を生成
•
•

C:\temp にデータあり、ここに結果を出力
読み込んだデータと指定した変数を解析

27

28.

まとめ • streamlit にて 1. 2. 3. 4. 超簡単にアプリが作れる SAS を(バッチにて)実行出来る SAS データも読み込める なのでアプリが作れたり遊べたりする • SAS を読み込む方法として saspy や sas7bdat というモジュールもあり • 次頁以降は streamlit 自体の説明です • データ: https://nfunao.web.fc2.com/files/python_intro2.zip 28

29.

メニュー • インストール • アプリの作成 → 実行 → 終了 • 「 SAS データを解析するアプリ」を streamlit で作成 • 各種出力と widget • session_state • レイアウト • その他 29

30.

テキスト出力 # app.py import streamlit as st st.title('Sample App.') st.header('* Display text') st.subheader('Example:') st.write('sample text 1') st.text('sample text 2') st.markdown('Washi: https://nfunao.web.fc2.com/') st.divider() st.latex(r''' e^{i\pi} + 1 = 0 ''') st.caption('note: latex output') st.code('for i in range(5): print(i)') 30

31.

テキスト出力: st.write() が便利 # app.py import streamlit as st import pandas as pd st.title('Sample App.') markdown = """ # Title ## Subtitle ### sample text ```python for i in range(5): print(i) ``` """ st.markdown(markdown) df = pd.DataFrame([[0,1,2], [3,4,5]]) st.write(df) 31

32.

データ出力 # app.py import streamlit as st import pandas as pd st.title('Sample App.') df = pd.DataFrame([[0,1,2], [3,4,5]]) df # magic command st.write(df) st.dataframe(df) st.table(df) st.json({'col1':'red','col2':'green'}) 32

33.

グラフ出力 # app.py import streamlit as st import pandas as pd import numpy as np df = pd.DataFrame({ "x": 3*np.random.rand(10), "y": 3*np.random.rand(10), "g": np.random.choice(["A", "B"], 10)}) st.bar_chart(df[["x","y"]]) st.line_chart(df[["x","y"]]) st.scatter_chart(df,x="x",y="y") 33

34.

グラフ出力: pyplot 経由 # app.py import streamlit as st import pandas as pd import numpy as np import matplotlib.pyplot as plt df = pd.DataFrame({ "x": 3*np.random.rand(10), "y": 3*np.random.rand(10), "g": np.random.choice(["A", "B"], 10)}) fig, ax = plt.subplots() ax.hist(df["x"]) st.pyplot(fig) 34

35.

Widget Widget Button Checkbox Color Picker Date Editor Date Input Download Button File Uploader Link Button Multi-line Text Input Multiselect Widget Numeric Input Radio Button Select widget Single-line Text Input Slider Slider to Select Items Time Input Function st.button('Label') st.checkbox('Label') st.color_picker('Label', '#00ff00') st.data_editor('Label', data-frame) st.date_input('Label') st.download_button('Label', contents) st.file_uploader('Label') st.link_button("Label", "https://xxx.com") st.text_area('Label') st.multiselect('Label', [1,2]) st.number_input('Label') st.radio('Label:', ['option 1','option 2']) st.selectbox('Label', [1,2]) st.text_input('Label') st.slider('Label', min_value=0, max_value=5) st.select_slider('Label', options=[1,'2']) st.time_input('Label') 35

36.
[beta]
Widget: button & checkbox
# app.py
import streamlit as st
import pandas
as pd
import numpy
as np
df = pd.DataFrame({
"x": 3*np.random.rand(10),
"y": 3*np.random.rand(10),
"g": np.random.choice(["A", "B"], 10)})

if st.button(label='Click'):
st.write('Clicked!')
var = st.columns(2)
x
= var[0].checkbox(label='Var x')
y
= var[1].checkbox(label='Var y')
vars = []
if x:
vars.append('x')
if y:
vars.append('y')
st.line_chart(df[vars])

36

37.
[beta]
Widget: ファイルのダウンロード
# app.py
import streamlit as st
import pandas

as pd

import numpy

as np

df = pd.DataFrame({
"x": 3*np.random.rand(10),

ボタンをクリックするとデータフレームが
CSV形式にてダウンロードされる

"y": 3*np.random.rand(10),
"g": np.random.choice(["A", "B"], 10)})
csv = df.to_csv().encode('SHIFT-JIS')

st.download_button(label='Download',
data=csv, file_name='output.csv',
mime='text/csv')
37

38.

Widget: ファイルのアップロード # app.py import streamlit as st import pandas as pd import numpy as np file = st.file_uploader("Choose a CSV file", type='csv') if file is not None: df = pd.read_csv(file) st.write(df) 38

39.

Widget: CSV のアップロード & 数値変数のグラフ # app.py import streamlit as st import pandas as pd import numpy as np file = st.file_uploader("Choose a CSV file", type='csv') if file is not None: df = pd.read_csv(file) st.write(df.head()) vars = [c for c in df.columns] column = st.selectbox("Variable", vars) numeric_vars = df.select_dtypes("number").columns if column in numeric_vars: st.line_chart(df[column]) 39

40.

Widget: CSV のアップロード & 数値変数のグラフ # app.py import streamlit as st import pandas as pd import numpy as np file = st.file_uploader("Choose a CSV file", type='csv') if file is not None: df = pd.read_csv(file) st.write(df.head()) vars = [c for c in df.columns] x = st.selectbox("Var x", vars) y = st.selectbox("Var y", vars) numeric_vars = df.select_dtypes("number").columns if x in numeric_vars and y in numeric_vars: st.scatter_chart(df, x=x, y=y) 40

41.

メニュー • インストール • アプリの作成 → 実行 → 終了 • 「 SAS データを解析するアプリ」を streamlit で作成 • 各種出力と widget • session_state • レイアウト • その他 41

42.

session_state # app.py import streamlit as st st.title('Sample App.') x = 0 if st.button("Add"): x = x + 1 st.write("x = ", x) ボタンをクリックすると変数 x に 値がどんどん足されるはずだが 何回クリックしても 1 のまま… 42

43.

session_state • streamlit は widget からの入力 ⇒ 値が更新されると、プログラムが 一番上から再実行される → 変数は再実行されると初期化されるものも • widget からの入力があった際、変数の値を保持したい場面がある ⇒ session_stete を用いることで変数の値を保持することが出来る • streamlit の各 widget は 1 つの key と 1 つの value を持ち(≒辞書型)、 key が各 widget の ID の役割を果たす • session_state は streamlit で用意されている辞書型のオブジェクトで、 key と value で各 widget の値を保持することが出来る • 以下では key=x と value=1 を session_state に追加している(同じ挙動) st.session_state['x'] = 1 st.session_state.x = 1 43

44.

session_state: 改善例 # app.py import streamlit as st st.title('Sample App.') if "x" not in st.session_state: st.session_state["x"] = 0 if st.button('Add'): st.session_state["x"] += 1 st.write("x = ", st.session_state['x']) • • • ボタンをクリックすると変数 x に 値がどんどん足される ただし、widget(例えばkey="id")のvalue は st.session_state["id"] で取得すること (直接代入の形で取得するとエラーの原因になり得る) session_state は「変数を保管する」他に「 widget の value を呼び出す」機能もある 参考: 覚えておきたい Streamlit での変数取り扱い( session_stete の注意点) https://qiita.com/NewYorki/items/176c8861987d8d0b2794 44

45.

session_state: 数値変数のグラフ # app.py import streamlit as st import pandas as pd import numpy as np file = st.file_uploader("Choose a CSV file", type='csv') if file is not None: df = pd.read_csv(file) st.write(df.head()) ボタンをクリックすると selectbox に変数情報が 入るが、変数を変更する とプログラムが再実行 されるため、if st.button() が通らなくなり不具合が 起きる if st.button('Plot'): vars = [c for c in df.columns] column = st.selectbox("Variable", vars) numeric_vars = df.select_dtypes("number").columns if column in numeric_vars: st.line_chart(df[column]) 45

46.

session_state: 数値変数のグラフ(改善例) # app.py import streamlit as st import pandas as pd import numpy as np if "is_button" not in st.session_state: st.session_state["is_button"] = False file = st.file_uploader("Choose a CSV file", type='csv') if file is not None: df = pd.read_csv(file) st.write(df.head()) if st.button('Plot') or st.session_state["is_button"]: st.session_state["is_button"] = True vars = [c for c in df.columns] column = st.selectbox("Variable", vars) ボタンをクリックすると ボタンをクリックすると selectbox selectbox に変数情報が に変数情報が 入るが、変数を変更する 入り、変数を変更しても 不具合は起きない とプログラムが再実行 されるため、if st.button() が通らなくなり不具合が 起きる numeric_vars = df.select_dtypes("number").columns if column in numeric_vars: st.line_chart(df[column]) 46

47.

メニュー • インストール • アプリの作成 → 実行 → 終了 • 「 SAS データを解析するアプリ」を streamlit で作成 • 各種出力と widget • session_state • レイアウト • その他 47

48.

レイアウト: sidebar • レイアウトに関する操作(例えば sidebar )は 2 通りの方法がある • st モジュールに対して行っていた操作を st.sidebar に対して行う • with st.sidebar の中で操作を行う(こちらの方が楽そう) # app.py import streamlit as st st.title('Sample App.') st.sidebar.title("Sidebar Title") st.sidebar.write('sample text 1') if st.sidebar.button(label='Button 1'): st.sidebar.write('Clicked!') with st.sidebar: st.divider() st.subheader('Example:') if st.button(label='Button 2'): st.write('Clicked!') 48

49.

レイアウト: column # app.py import streamlit as st # col1, col2 = st.columns(2) # equal witdth col1, col2 = st.columns([2, 1]) with col1: st.title('Sample App.') if st.button(label='Button 1'): st.write('Clicked!') with col2: st.subheader('Example:') if st.button(label='Button 2'): st.write('Clicked!') 49

50.

レイアウト: tab # app.py import streamlit as st import pandas as pd import numpy as np file = st.file_uploader("Choose a CSV file", type='csv') if file is not None: df = pd.read_csv(file) st.write(df.head()) if st.button('Plot'): vars = [c for c in df.columns] column = st.selectbox("Variable", vars) numeric_vars = df.select_dtypes("number").columns if column in numeric_vars: st.line_chart(df[column]) 50

51.

レイアウト: expander(部品の表示・非表示切り替え) # app.py import streamlit as st st.title('Sample App.') if st.button(label='Button 1'): st.write('Clicked!') with st.expander("See More..."): st.subheader('Example:') if st.button(label='Button 2'): st.write('Clicked!') 51

52.
[beta]
レイアウト: container(複数の部品をまとめる)
# app.py
import streamlit as st
import pandas
as pd
import numpy
as np
st.title('Sample App.')
df = pd.DataFrame({
"x": 3*np.random.rand(10),
"y": 3*np.random.rand(10),
"g": np.random.choice(["A", "B"], 10)})
with st.container(border=True):
st.write("Scatter Plot")
st.scatter_chart(df,x="x",y="y",color="g")
st.write("The number of the points is 10.")
st.write("This sentence is outside the container.")
52

53.

レイアウト: 複数ページ c:\temp • import streamlit as st main.py pages sub.py C:\temp\main.py ← こちらを実行 st.set_page_config(page_title="Main", page_icon="") st.title("Main page") • C:\temp\pages\sub.py import streamlit as st st.set_page_config(page_title="Sub", page_icon="") st.title("Sub page") 53

54.

レイアウト: その他 • ページ設定: set_page_config https://docs.streamlit.io/develop/apireference/configuration/st.set_page_config • テーマの変更 https://docs.streamlit.io/develop/concepts/configuration/theming 54

55.

メニュー • インストール • アプリの作成 → 実行 → 終了 • 「 SAS データを解析するアプリ」を streamlit で作成 • 各種出力と widget • session_state • レイアウト • その他 55

56.
[beta]
アプリ作成例: 解析ソフト
# app.py
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
st.title("Upload a CSV and Analyze Data")
uploaded_file = st.file_uploader("Choose a CSV file",
type="csv")
if uploaded_file is not None:
df = pd.read_csv(uploaded_file)
st.write("DataFrame Preview:")
st.write(df.head())

vars = [c for c in df.columns]
value = st.selectbox("Variable", vars)
group = st.selectbox("Group", vars)
if st.checkbox('Grouped'):
summary_stats = df.groupby(group)[value].describe()
st.subheader("Summary Statistics by Group")
st.write(summary_stats)
st.subheader("Histogram by Group")
groups = df[group].unique()
num_groups = len(groups)

if num_groups <11:
fig, axs = plt.subplots(num_groups, 1, figsize=(10, 5 * num_groups))
if num_groups == 1:
axs = [axs]

for ax, grp in zip(axs, groups):
group_data = df[df[group] == grp][value]
ax.hist(group_data, bins=20, alpha=0.7, color='blue',
edgecolor='black')
ax.set_title(f'Histogram of Values for Group {grp}')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
plt.tight_layout()
st.pyplot(fig)
else:
summary_stats = df[value].describe()
st.subheader("Summary Statistics by Group")

st.write(summary_stats)
st.subheader("Histogram")
fig, ax = plt.subplots(1, 1, figsize=(10, 5))
ax.hist(df[value], bins=20, alpha=0.7, color='blue',

edgecolor='black')
ax.set_title(f'Histogram of Values')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
plt.tight_layout()
st.pyplot(fig)

56

57.

アプリ作成例: https://f5lppq2xsk877wluqd3gj3.streamlit.app/ 57

58.

Streamly Streamlit Assistant • https://streamly.streamlit.app/ streamlit 用生成 AI がプログラム作成をサポート! 58

59.

参考文献 • Streamlit documentation https://docs.streamlit.io/ • Streamlit API cheat sheet https://docs.streamlit.io/develop/quick-reference/cheat-sheet • Streamlit Magic Cheat Sheets https://cheat-sheets.streamlit.app/ • 覚えておきたい Streamlit での変数取り扱い( session_stete の注意点) https://qiita.com/NewYorki/items/176c8861987d8d0b2794 • Pandas User's Guide https://pandas.pydata.org/pandas-docs/stable/user_guide/index.html • 【コマンドプロンプト】目的別コマンド一覧 https://techmania.jp/blog/cmd0002/ • 舟尾 暢男「streamlit でアプリ作成」 https://nfunao.web.fc2.com/ https://nfunao.web.fc2.com/files/python_intro2.zip 59

60.

- End of File -