Skip to content

Commit edbf852

Browse files
committed
[update] update PySimpleGUI_PyWebIO_Streamlit/README.md
1 parent 1c03d88 commit edbf852

File tree

16 files changed

+1051
-0
lines changed

16 files changed

+1051
-0
lines changed

PySimpleGUI_PyWebIO_Streamlit/README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,114 @@ matplotlibとかbokehとかnumpyのインストール方法は省略するよ。
254254
<img src="https://camo.qiitausercontent.com/057b5122f3c2850254f16c95e74145856c947204/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f38313835312f64616139313534642d316161642d353362312d383664382d3330383731316462343962612e706e67" width="400" height="500">
255255

256256

257+
# streamlitで遊ぼう!
258+
[streamlitで遊ぼう! updated at 2021-01-13](https://qiita.com/irisu-inwl/items/9d49a14c1c67391565f8)
259+
260+
repository: https://github.com/irisu-inwl/streamlit-tutorial
261+
動作確認環境: windwos10, docker for windows
262+
263+
264+
# Streamlitで爆速アプリ開発
265+
[Streamlitで爆速アプリ開発 posted at 2020-12-14](https://qiita.com/nyax/items/fc418416e97a12141d0a)
266+
267+
## デプロイもできちゃう
268+
```
269+
Streamlitでデプロイもできてしまう、、!
270+
https://docs.streamlit.io/en/stable/deploy_streamlit_app.html
271+
に沿ってするとできます
272+
```
273+
274+
# 【Python】LINEのグルチャ履歴をヌルヌル動くグラフにしてみた~原理からWebアプリ化まで~
275+
[【Python】LINEのグルチャ履歴をヌルヌル動くグラフにしてみた~原理からWebアプリ化まで~ posted at 2021-02-17](https://qiita.com/adumaru0828/items/4be1c07aeb461f7d9341)
276+
```
277+
app.py
278+
```
279+
280+
# Streamlitで作成した株価アプリをWEB公開した(キャッシュ説明あり)
281+
[Streamlitで作成した株価アプリをWEB公開した(キャッシュ説明あり)updated at 2021-02-01](https://qiita.com/morita-toyscreation/items/c9c873bce8d54cfe5b36)
282+
283+
## キャッシュ化
284+
```
285+
このままWEB公開するとBigQueryアクセスが多くなるのでキャッシュ化を行う
286+
@st.cacheデコレーターを付けることで返り値をキャッシュする
287+
@st.cacheは引数種類別にキャッシュする
288+
2回目以降はキャッシュを使いBigQueryにアクセスしない
289+
allow_output_mutationをTrueにすると返り値が変わってもエラーにならない
290+
```
291+
292+
```
293+
@st.cache(allow_output_mutation=True, suppress_st_warning=True)
294+
def _get_stock(stock_no: str, start_date: str, end_date: str):
295+
```
296+
297+
## Docker環境準備
298+
```
299+
Dockerfile作成
300+
Cloud Runで動かすのでポート8080に設定する
301+
```
302+
303+
```
304+
FROM python:3.7.4
305+
306+
WORKDIR /app
307+
ADD . /app
308+
309+
RUN apt-get update && apt-get clean;
310+
RUN pip install --upgrade pip
311+
RUN pip install -r requirements.txt
312+
313+
ENV TZ Asia/Tokyo
314+
ENV LANG ja_JP.UTF-8
315+
ENV LANGUAGE ja_JP:ja
316+
ENV LC_ALL ja_JP.UTF-8
317+
ENV GOOGLE_APPLICATION_CREDENTIALS /app/config/xxx.json
318+
319+
EXPOSE 8080
320+
321+
CMD streamlit run --server.port 8080 app.py
322+
```
323+
324+
```
325+
$ docker build -t kabu-analysis .
326+
```
327+
328+
```
329+
$ docker run --name kabu-analysis \
330+
-p 8080:8080 -v ~/Sites/kabu-analysis/:/app -it --rm kabu-analysis
331+
```
332+
333+
# PyCaretとStreamlitでAutoMLのGUIツールをさくっと作ってみる
334+
[PyCaretとStreamlitでAutoMLのGUIツールをさくっと作ってみる posted at 2021-02-21](https://qiita.com/ryoshi81/items/e9560ade1f0adedbaf6c)
335+
336+
337+
# 【Streamlit】JavaScriptが嫌いだからPythonだけでWebアプリをつくる
338+
[【Streamlit】JavaScriptが嫌いだからPythonだけでWebアプリをつくる updated at 2020-08-08](https://qiita.com/SPShota/items/a63e19807779175aa29b)
339+
340+
```
341+
フロント(SPA)開発案件2つのプレイングマネージャーと開発リーダーやってますが、JavaScriptが死ぬほど嫌いです。
342+
ブラウザ上で動作するスクリプトなので仕方ないし、async-awaitで大分便利になったけど、非同期処理がやっぱり好きじゃないです。
343+
344+
JavaとかPythonとかそれなりの期間触った言語は大概「みんな違ってみんないい」みたいな感じになるんですが、JavaScriptだけそうならないので本当に嫌いなんだと思います。
345+
346+
因みにCSSはもっと嫌いです。
347+
348+
機械学習モデルの構築をPythonで実装することは多いと思いますが、ちょっとしたデモアプリでも作るとなると、フロント側はどうしてもHTML、JavaScript、CSSで組まないといけないです。
349+
350+
Jupyter Notebookも選択肢に入るかもしれませんが、Webアプリと比べると表現の自由度は下がるし、コードセルが見えるのはなんか煩雑に見えます。
351+
352+
嫌いかどうかは置いておいて、フロント開発の煩わしさを抱えている人って結構いるんじゃないかなって思ってます。 ・・・いるよね?
353+
7月の連休中に触ったStreamlitっていうライブラリが滅茶苦茶便利だったので、今回はこれを使ってPython "だけ" でWEBアプリを作ってみようと思います!
354+
```
355+
356+
## WEBUIを使ってインタラクティブなアプリにする
357+
```
358+
ここまでだと、Jupyterで可視化してるのとあまり差がないのでWEBアプリケーションらしいインタラクションを実装します。
359+
360+
データ取得処理の後に日付の範囲指定をするコンポーネントの表示処理を追加して、データフレームを絞り込みます。
361+
bodyの場合はst.コンポーネント名、サイドバーにの場合、st.sidebar.コンポーネント名でUIコンポーネントを追加します。
362+
```
363+
364+
257365
# Troubleshooting
258366

259367

PySimpleGUI_PyWebIO_Streamlit/requirements.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ astor==0.8.1
55
async-generator==1.10
66
attrs==21.2.0
77
backcall==0.2.0
8+
bar-chart-race==0.1.0
89
base58==2.1.0
910
bleach==4.0.0
1011
blinker==1.4
@@ -28,8 +29,10 @@ ipykernel==6.0.3
2829
ipython==7.26.0
2930
ipython-genutils==0.2.0
3031
ipywidgets==7.6.3
32+
japanize-matplotlib==1.1.3
3133
jedi==0.18.0
3234
Jinja2==3.0.1
35+
joblib==1.0.1
3336
jsonschema==3.2.0
3437
jupyter-client==6.1.12
3538
jupyter-core==4.7.1
@@ -53,6 +56,7 @@ parso==0.8.2
5356
pefile==2019.4.18
5457
pickleshare==0.7.5
5558
Pillow==7.2.0
59+
plotly==5.1.0
5660
plyer==1.4.3
5761
prometheus-client==0.11.0
5862
prompt-toolkit==3.0.19
@@ -84,13 +88,19 @@ qt5-tools==5.15.2.1.0.1
8488
QtPy==1.9.0
8589
requests==2.26.0
8690
rethinkdb==2.4.7
91+
scikit-learn==0.24.2
92+
scipy==1.7.1
93+
seaborn==0.11.1
8794
Send2Trash==1.7.1
8895
shiboken2==5.15.2
8996
six==1.15.0
97+
sklearn==0.0
9098
smmap==4.0.0
9199
streamlit==0.86.0
100+
tenacity==8.0.1
92101
terminado==0.10.1
93102
testpath==0.5.0
103+
threadpoolctl==2.2.0
94104
toml==0.10.2
95105
toolz==0.11.1
96106
tornado==6.1
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import numpy as np
2+
import pandas as pd
3+
import matplotlib.pyplot as plt
4+
import matplotlib.animation as animation
5+
import streamlit as st
6+
import streamlit.components.v1 as components
7+
import bar_chart_race as bcr
8+
from PIL import Image
9+
from io import StringIO
10+
from datetime import datetime
11+
from collections import defaultdict
12+
import japanize_matplotlib
13+
import plotly.graph_objects as go
14+
15+
# ロゴ
16+
logo_image = Image.open('src/logo.png')
17+
st.image(logo_image)
18+
19+
# メイン画像
20+
main_image = Image.open('src/mainimg.png')
21+
st.image(main_image)
22+
23+
"""
24+
# 遊び方
25+
26+
以下の手順で、誰でも簡単に**バーチャートレース(ぬるぬる動くグラフ)**を作ることができます。
27+
28+
1. LINEのトーク履歴をtxtファイル形式で保存する(所要時間:1分)<方法は[コチラ]("https://appllio.com/line-talk-history-send-mail")>
29+
2. 保存したtxtファイルをアップロードする(所要時間:30秒)
30+
3. お好みでカスタマイズして完成!(所要時間:30秒)
31+
32+
# さっそく遊んでみる
33+
LINEトーク履歴(txtファイル)を選択してください
34+
"""
35+
uploaded_file = st.file_uploader("""※期間が1年以上になると動画処理が終わらない可能性があります""",type="txt",)
36+
st.markdown("**(画面左上からサイドバーを開くと自由にカスタマイズできます)**")
37+
"""
38+
---
39+
"""
40+
41+
42+
#####サイドバー#####
43+
st.sidebar.markdown("# ⚙️カスタマイズオプション")
44+
45+
st.sidebar.markdown("### 【データフレーム】")
46+
df_category = st.sidebar.radio("データフレームの種類を選択してください", ('標準', '累積和','標準<markdown>', '累積和<markdown>'))
47+
48+
st.sidebar.markdown("### 【折れ線グラフ】")
49+
line_title = st.sidebar.text_input('表示タイトル', 'グループチャット発言回数の推移')
50+
line_category = st.sidebar.radio("折れ線グラフの種類を選択してください", ('累積和','標準'))
51+
52+
st.sidebar.markdown("### 【ヒートマップ】")
53+
heat_title = st.sidebar.text_input('表示タイトル', 'グループチャット発言回数')
54+
heat_colorscale = st.sidebar.radio("カラースケールを選択してください", ('Defalut','Blackbody','Bluered','Blues','Earth','Electric','Greens','Greys','Hot','Jet','Picnic','Portland','Rainbow','RdBu','Reds','Viridis','YlGnBu','YlOrRd'))
55+
st.sidebar.markdown("### 【バーチャートレース】")
56+
bcr_title = st.sidebar.text_input('表示タイトル', 'グループチャット発言回数ランキング')
57+
n_bars = st.sidebar.slider('ランキング上位表示人数', min_value=1,max_value=20,value=2)
58+
st.sidebar.write('↪',n_bars, '人')
59+
from_date = str(st.sidebar.date_input('表示期間(開始)',value=datetime(2000,1,1)))
60+
to_date = str(st.sidebar.date_input('表示期間(終了)',value=datetime(2100,12,31)))
61+
steps_per_period = st.sidebar.slider('ピリオド毎のステップ数', min_value=1,max_value=50,value=10)
62+
st.sidebar.write('↪',steps_per_period)
63+
period_length = st.sidebar.slider('1ピリオドの長さ', min_value=100,max_value=1000,value=500)
64+
st.sidebar.write('↪',period_length)
65+
#####サイドバー#####
66+
67+
68+
if uploaded_file is not None: # ファイルがアップロードされた場合
69+
70+
bytes_data = uploaded_file.getvalue()
71+
stringio = StringIO(uploaded_file.getvalue().decode("utf-8"))
72+
tmp_names = defaultdict(int) # グループメンバーの名前を格納するリスト
73+
stringio_list = []
74+
# グループの人数をカウント
75+
for i,data in enumerate(stringio):
76+
data_list = list(map(str,data.split())) # txtファイルの各行のデータをリスト化
77+
stringio_list.append(data_list)
78+
if i < 2: #2行目までのタイトルと保存日時はスキップ
79+
continue
80+
if len(data_list) <= 2: # 空白行&日付行はスキップ
81+
continue
82+
name = data_list[1]
83+
if not data_list[0][0].isdigit() or name in ['Group','You','☎']: # システムメッセージ等を除外する
84+
continue
85+
tmp_names[name] += 1 # メンバーリストに追加
86+
names = [key for key in tmp_names.keys() if tmp_names[key] >= 5] # 発言回数5回以上のメンバーだけ残す
87+
chat_count = [] # 日付ごとの発言カウントを格納するリスト
88+
daily_data = [] # 1日のデータを格納するリスト
89+
for i,data_list in enumerate(stringio_list):
90+
91+
if i < 2: #2行目までのタイトルと保存日時はスキップ
92+
continue
93+
94+
if len(data_list) < 1: # 空白行はスキップ
95+
continue
96+
97+
if len(data_list[0])>=10 and data_list[0][4]=='/' and data_list[0][7]=='/': # 日付の行
98+
if daily_data:
99+
if daily_data[0] <= to_date: # 表示期間以内
100+
chat_count.append(daily_data) # 日付の行が来たタイミングで先日の発言回数をchat_countリストに追加
101+
else: # 表示期間外
102+
break
103+
104+
date = data_list[0].replace('/','-')[:10] # 2020/01/01 ---> 2020-01-01 (日付表示を変更)
105+
if from_date <= date: # 表示期間内
106+
daily_data = [date]+[0]*(len(names)) # その日のデータを格納するリストを用意 ['2020-01-01',0,0,0,...]
107+
continue
108+
else:
109+
daily_data = None
110+
111+
if len(data_list) >= 3:
112+
name = data_list[1]
113+
if name in names and daily_data: # 発言表示の行の場合
114+
daily_data[names.index(name)+1] += 1 # 発言者ごとの発言数をインクリメントする
115+
if daily_data and daily_data[0] <= to_date:
116+
chat_count.append(daily_data)
117+
chat_count = np.array(chat_count) # 発言カウントリストをnumpy配列に変換
118+
original_df = pd.DataFrame(chat_count)
119+
original_df.columns = ['日付'] + names # 列インデックスに氏名を指定
120+
original_df = original_df.set_index('日付') # 行インデックスに日付を指定
121+
original_df = original_df.astype(dict(zip(names,['int64']*len(names)))) # カウントした発言数を整数(int64)型に変換
122+
chat_count[:,1:len(names)+1] = np.cumsum(np.array(chat_count[:,1:len(names)+1],dtype=int),axis=0) # 日付以外の列に関して、縦方向に累積和を取る
123+
df = pd.DataFrame(chat_count)
124+
df.columns = ['日付'] + names # 列インデックスに氏名を指定
125+
df = df.set_index('日付') # 行インデックスに日付を指定
126+
df = df.astype(dict(zip(names,['int64']*len(names)))) # カウントした発言数を整数(int64)型に変換
127+
128+
# データフレーム
129+
st.write(f'## データフレーム({df_category})')
130+
if df_category == '標準':
131+
st.write(original_df)
132+
elif df_category == '累積和':
133+
st.write(df)
134+
elif df_category == '標準<markdown>':
135+
st.markdown(original_df.to_markdown())
136+
else:
137+
st.markdown(df.to_markdown())
138+
139+
# 折れ線グラフ
140+
st.write(f'## 折れ線グラフ({line_category})')
141+
pd.options.plotting.backend = "plotly"
142+
if line_category == "標準":
143+
fig_line = original_df.plot(title=line_title, template="simple_white",
144+
labels=dict(index="日付", value="回数", variable="メンバー"))
145+
else:
146+
fig_line = df.plot(title=line_title, template="simple_white",
147+
labels=dict(index="日付", value="回数", variable="メンバー"))
148+
st.write(fig_line)
149+
150+
# ヒートマップ
151+
st.write('## ヒートマップ')
152+
if heat_colorscale == 'Defalut':
153+
heat_colorscale = None
154+
fig_heat = go.Figure(data=go.Heatmap(
155+
z=original_df,
156+
x=names,
157+
y=list(df.index),
158+
colorbar=dict(title='回数'),
159+
colorscale=heat_colorscale,
160+
hoverongaps = True)
161+
)
162+
fig_heat.update_xaxes(title="メンバー")
163+
fig_heat.update_yaxes(title="日付")
164+
fig_heat.update_layout(title=heat_title)
165+
st.write(fig_heat)
166+
167+
# バーチャートレース
168+
st.write('## バーチャートレース')
169+
html = bcr.bar_chart_race(df,title=bcr_title,n_bars=n_bars,figsize=(4,3),steps_per_period=steps_per_period,period_length=period_length)
170+
components.html(html._repr_html_(),width=10000,height=7500)
171+
172+
# 注意事項
173+
st.markdown("※本サービスは、アップロードされたLINEトーク履歴(個人情報を含む)を使用して処理を行います。アップロードされた情報は保存されることなく処理が終了した時点で破棄されますが、心配な方は利用を控えてください。")
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import time
2+
3+
import streamlit as st
4+
5+
6+
@st.cache
7+
def progress_cache(i):
8+
time.sleep(0.05)
9+
10+
11+
def progress_no_cache(i):
12+
time.sleep(0.05)
13+
14+
15+
def view_bar(func):
16+
# Add a placeholder
17+
latest_iteration = st.empty()
18+
bar = st.progress(0)
19+
20+
for i in range(100):
21+
# Update the progress bar with each iteration.
22+
latest_iteration.text(f'Iteration {i+1}')
23+
bar.progress(i + 1)
24+
func(i)
25+
26+
27+
st.title('Cache example')
28+
st.write('Starting a long computation with cache...')
29+
view_bar(progress_cache)
30+
31+
st.write('Starting a long computation without cache...')
32+
view_bar(progress_no_cache)
33+
34+
st.write('...and now we\'re done!')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
404: Not Found

0 commit comments

Comments
 (0)