前面所測試的五個 Streamlit 內建統計圖函式是用來快速繪製常用的統計圖, 主打簡單易用毋須太複雜的設定, 但也因此而無法做客製化的細節調整, 而且目前也僅提供這五種圖表的快捷函式而已, 如果要做客製化設定或繪製其它圖表, 可以利用 Streamlit 的 st.pyplot() 函式來解決.
Streamlit 的 st.pyplot() 函式提供輸出 Matplotlib 生成圖表的支援, 關於 Matplotlib 用法參考 :
Matplotlib 用法有兩種 : 函數式用法與物件導向式用法, 函數式用法使用 matplotlib.pyplot 模組提供的函數直接繪圖, 函數直接操作全局圖表且隱式管理 Figure 和 Axes 物件, 其優點為簡潔直觀, 程式碼簡短, 適合快速繪製簡單圖表或做原型設計用; 缺點是當圖表複雜時要控制細節較困難, 程式碼可讀性可能會降低. 而物件導向用法則是顯式地建立 Figure 和 Axes 物件, 透過物件方法設置屬性, 程式碼較結構化, 適合多子圖或複雜佈局.
st.pyplot 的參數結構如下 :
st.pyplot(fig=None, clear_figure=True, **kwargs)
參數說明如下表 :
| st.pyplot() 參數 | 說明 |
|---|---|
| fig | Matplotlib 的 Figure 物件,若未指定則顯示當前預設圖(即 plt 畫的圖)。 |
| clear_figure | 顯示圖表後是否自動清除該圖(預設為 True),避免圖重複顯示。 |
| **kwargs | 傳給 Matplotlib 的關鍵字參數例如 dpi 等。 |
注意, 此處的 **kwargs 是 Streamlit 保留給未來擴充功能用的, 與 Matplotlib 繪圖函式 plot() 的關鍵字參數完全無關, 將 plot() 的關鍵字參數傳給 st.pyplot() 並無作用.
要在 Streamlit 中顯示 Matplotlib 繪製的圖片只要將 Figure 畫布物件傳給 st.pyplot() 即可, Streamlit 會將 Matplotlib 生成的圖表嵌入網頁頁面中. 注意, 不要在程式末尾呼叫 plt.show(), 那是在本地桌面環境用來跳出視窗顯示圖片用的.
# st-pyplot-test-1.py
import matplotlib.pyplot as plt
import numpy as np
import streamlit as st
# 顯示中文:使用微軟正黑體
plt.rcParams['font.family']=['Microsoft JhengHei']
x=np.array([1, 2, 3, 4])
y=np.array([10, 20, 25, 30])
# 繪製折線圖
plt.plot(x, y, color='blue', marker='o') # 繪製線條並設置顏色和標記
plt.title('Matplotlib 折線圖 (函數式)') # 設置標題
plt.xlabel('X 軸') # X 軸標籤
plt.ylabel('Y 軸') # Y 軸標籤
plt.grid(True) # 顯示網格
# 顯示圖表
fig=plt.gcf() # 取得目前的 Figure 物件
st.pyplot(fig)
此例因為函數式用法為隱式管理 Figure 和 Axes 物件, 因此要用 plt.gcf() 取得目前的 Figure 畫布物件並將其傳給 st.pyplot() 顯示, 結果如下 :
下面範例使用物件導向式繪製圖片 :
測試 2 : 顯示 Matplotlib 生成的折線圖 (物件導向式) [看原始碼]
# st-pyplot-test-2.py
import matplotlib.pyplot as plt
import numpy as np
import streamlit as st
# 顯示中文:使用微軟正黑體
plt.rcParams['font.family']=['Microsoft JhengHei']
x=np.array([1, 2, 3, 4])
y=np.array([10, 20, 25, 30])
# 建立子圖傳回 Figure 和 Axes 物件
fig, ax=plt.subplots()
# 繪製折線圖
ax.plot(x, y, color='blue', marker='o') # 在指定 Axes 上繪圖
ax.set_title('Matplotlib 折線圖 (物件導向)') # 設置標題
ax.set_xlabel('X 軸') # X 軸標籤
ax.set_ylabel('Y 軸') # Y 軸標籤
ax.grid(True) # 顯示網格
# 顯示圖表
st.pyplot(fig)
由於物件導向使用顯示管理 Figure 和 Axes 物件, 直接將 plt.subplots() 傳回的 Figure 物件傳給 st.pyplot() 即可, 結果如下 :
之前在測試內建長條圖函式 st.bar_chart() 時發現它對於兩個 Y 軸資料採用堆疊方式 (stacked) 繪製長條圖, 無法繪製群組式 (grouped) 長條圖, 這可以透過 Matplotlib 來實現, 如下面範例所示 :
測試 3 : 顯示 Matplotlib 生成的群組式垂直長條圖 [看原始碼]
# st-pyplot-test-3.py
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# 顯示中文:使用微軟正黑體
plt.rcParams['font.family']=['Microsoft JhengHei']
# 模擬每月營收資料
data=pd.DataFrame({
'月份': ['一月', '二月', '三月', '四月', '五月'],
'今年營收': [120000, 135000, 99000, 150000, 170000],
'去年營收': [110000, 125000, 95000, 145000, 160000]
})
st.subheader('今年 vs 去年前五個月營收比較')
# 準備資料
labels=data['月份']
this_year=data['今年營收']
last_year=data['去年營收']
x=np.arange(len(labels)) # 每個月的 x 座標
bar_width=0.35 # 長條寬度
# 建立圖表
fig, ax=plt.subplots()
ax.bar(x - bar_width/2, last_year, bar_width, label='去年營收', color='skyblue')
ax.bar(x + bar_width/2, this_year, bar_width, label='今年營收', color='orange')
# 設定圖表
ax.set_xlabel('月份')
ax.set_ylabel('營收')
ax.set_title('今年 vs 去年 每月營收比較')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()
ax.grid(axis='y', linestyle='--', alpha=0.5)
# 顯示圖表
st.pyplot(fig)
此例利用在 X 軸刻度左右移位長條寬度一半來放置今年與去年同期月份的兩條 bar 以達成群組目的, 結果如下 :
要改成用水平長條圖呈現只要改為呼叫 barh() 並且將 X 軸與 Y 軸交換即可 :
測試 4 : 顯示 Matplotlib 生成的群組式水平長條圖 [看原始碼]
# st-pyplot-test-4.py
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# 顯示中文:使用微軟正黑體
plt.rcParams['font.family']=['Microsoft JhengHei']
# 模擬每月營收資料
data=pd.DataFrame({
'月份': ['一月', '二月', '三月', '四月', '五月'],
'今年營收': [120000, 135000, 99000, 150000, 170000],
'去年營收': [110000, 125000, 95000, 145000, 160000]
})
st.subheader('今年 vs 去年前五個月營收比較(水平長條圖)')
# 準備資料
labels=data['月份']
this_year=data['今年營收']
last_year=data['去年營收']
y=np.arange(len(labels)) # 每個月的 y 座標
bar_height=0.35 # 長條高度
# 建立圖表
fig, ax=plt.subplots()
ax.barh(y - bar_height/2, last_year, bar_height, label='去年營收', color='skyblue')
ax.barh(y + bar_height/2, this_year, bar_height, label='今年營收', color='orange')
# 設定圖表
ax.set_ylabel('月份')
ax.set_xlabel('營收')
ax.set_title('今年 vs 去年 每月營收比較')
ax.set_yticks(y)
ax.set_yticklabels(labels)
ax.legend()
ax.grid(axis='x', linestyle='--', alpha=0.5)
# 顯示圖表
st.pyplot(fig)
計算 bar 左右偏移的方式相同, 但 X 與 Y 顛倒, 結果如下 :
下面是輸出 Matplotlib 隨機散布圖的範例 :
測試 5 : 顯示 Matplotlib 生成的隨機散布圖 [看原始碼]
# st-pyplot-test-5.py
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
# 顯示中文:使用微軟正黑體
plt.rcParams['font.family']=['Microsoft JhengHei']
plt.rcParams['axes.unicode_minus']=False # 正確顯示負號
# 建立隨機資料
rng=np.random.RandomState(0)
x=rng.randn(100)
y=rng.randn(100)
colors=rng.rand(100)
sizes=1000 * rng.rand(100)
# 建立圖表物件
fig, ax=plt.subplots()
# 繪製散佈圖
sc=ax.scatter(x, y, c=colors, s=sizes, alpha=0.3, cmap='hsv')
# 添加色條
fig.colorbar(sc, ax=ax)
# 設定標題
ax.set_title('Matplotlib 隨機散佈圖')
st.pyplot(fig)
此例利用 Numpy 產生 100 組隨機資料, 用它們來繪製大小色彩不同的圓圈, 注意, 此處因為刻度有負數, 必須將全域參數 plt.rcParams['axes.unicode_minus'] 設為 False 叫 Matplotlib 不要使用 Unicode 負號, 這樣才會正常顯示負號, 結果如下 :





沒有留言 :
張貼留言