Plotly 是一個功能強大且非常受歡迎的互動性資料視覺化工具, 支援折線圖, 長條圖, 散點圖, 地圖, 熱圖, 3D 圖表, 統計圖等數十種圖形, 底層使用 Javascript 開發, 但也支援 Python, Julia 與 R 等程式語言, 並可與 Pandas 資料結構高度整合, 生成的結果可匯出成 HTML檔方便嵌入到網頁中或發佈至網站. 參考 :
本系列所有測試文章參考 :
st.plotly_chart(fig, use_container_width=False, sharing="streamlit", theme="streamlit")
參數說明如下表 :
| st.plotly_chart() 參數 | 說明 |
|---|---|
| fig | 用 plotly.graph_objects 或 plotly.express 建立的 Plotly 畫布物件 |
| use_container_width | 是否讓圖表寬度自動填滿畫面容器 (True/False), 預設為 False |
| sharing | 圖表分享方式, 可用 "private", "public" 或 "streamlit" (預設) |
| theme | 圖表主題, 可設為 "none" (Plotly 樣式) 或 "streamlit" (預設) |
Plotly 提供兩種主要的使用方式, 第一種是透過原生模組 plotly.graph_objs. 這個模組提供許多繪圖類別, 例如 Scatter 用來建立圖形物件, Layout 用來設定圖表的標題與軸標籤等, 最後透過 Figure 將圖形與版面配置組合成一個圖表物件, 並傳遞給 st.plotly_chart() 顯示在 Streamlit 中.
這種方式屬於較低階的用法, 可讓開發者完全掌控圖表的外觀樣式, 例如標記 (marker) 的大小與顏色, 圖表標題, 軸標籤等. 需要注意的是, 在 Streamlit 應用中不需使用 plotly.offline 模組, 因此不必額外匯入整個 plotly 套件, 只需匯入 plotly.graph_objs 即可.
Plotly 的另一種用法是透過快捷模組 plotly.express, 它與 Pandas 有高度整合, 語法簡潔, 非常適合用於快速資料視覺化, 雖然 plotly.express 也支援使用串列作為資料來源, 但為了確保如 x, y, color, size 等參數能正確對應資料欄位, 建議先將資料轉換為 Pandas 的 DataFrame 結構, 否則可能會限制部分功能的使用或導致參數無法正確解析.
首先測試 plotly.graph_objs 模組的用法 :
測試 1 : 顯示 Plotly 生成的散布圖 (1) [看原始碼]
# st-plotly-test-1.py
import streamlit as st
import plotly.graph_objs as go
# 繪圖的資料
weight=[49, 65, 53, 45, 56, 47, 52, 61] # 體重
height=[159, 177, 156, 163, 164, 158, 166, 171] # 身高
# 建立 Scatter 圖形物件
scatter=go.Scatter(
x=weight,
y=height,
mode='markers',
marker=dict(size=10, color='blue')
)
# 建立 Layout 物件 (設定標題, 軸標籤等)
layout=go.Layout(
title='體重 vs 身高 散佈圖',
xaxis=dict(title='體重 (kg)'),
yaxis=dict(title='身高 (cm)')
)
# 建立 Figure 物件
fig=go.Figure(data=[scatter], layout=layout)
# 在 Streamlit 顯示圖表
st.plotly_chart(fig)
此例使用串列做為繪圖的資料, 將它們直接傳給 Scatter() 的 x, y 參數建立圖形物件. 注意, 由於 Plotly 支援多圖形 trace, 所以 Figure() 的 data 參數需傳入一個串列 (即使只有一個圖形也是), 結果如下 :
下面用 plotly.express 來改寫上面的散布圖範例 :
測試 2 : 顯示 Plotly 生成的散布圖 (2) [看原始碼]
# st-plotly-test-2.py
import streamlit as st
import plotly.express as px
# 繪圖的資料
weight=[49, 65, 53, 45, 56, 47, 52, 61] # 體重
height=[159, 177, 156, 163, 164, 158, 166, 171] # 身高
data={'weight': weight, 'height': height} # 打包成字典
# 建立 Figure 物件
fig=px.scatter(
data,
x='weight',
y='height',
title='體重 vs 身高 散佈圖',
labels={'weight': '體重 (kg)', 'height': '身高 (cm)'}
)
fig.update_traces(marker=dict(size=10, color='blue'))
# 在 Streamlit 顯示圖表
st.plotly_chart(fig)
此例將 x, y 軸串列先打包成 data 字典, 然後再傳給 px.scatter() 建立 Figure 物件後傳給 st.plotly_chart() 即可快速繪製散點圖. 注意, 圖表標題要用 title 參數指定, 軸標籤要用 labels 參數以字典指定, 而標記樣式 (marker) 則是要用 Figure 物件的 update_traces() 方法傳入 marker 參數指定, 結果與上例相同 :
Plotly 的 plotly.express 模組與 Pandas 高度整合, 可以將 DataFrame 直接傳入 px.scatter() 繪製圖表, 如下面範例所示 :
測試 3 : 顯示 Plotly 生成的散布圖 (3) [看原始碼]
# st-plotly-test-2.py
import streamlit as st
import plotly.express as px
import pandas as pd
# 繪圖的資料
df=pd.DataFrame({
'weight': [49, 65, 53, 45, 56, 47, 52, 61],
'height': [159, 177, 156, 163, 164, 158, 166, 171]
})
# 建立 Figure 物件
fig=px.scatter(
df,
x='weight',
y='height',
title='體重 vs 身高 散佈圖',
labels={'weight': '體重 (kg)', 'height': '身高 (cm)'}
)
fig.update_traces(marker=dict(size=10, color='blue'))
# 在 Streamlit 顯示圖表
st.plotly_chart(fig)
結果與上例相同.
plotly.express 模組的 Figure 物件有一個功能強大的 update_layout() 方法, 可以用它來調整整個圖表的外觀樣式與配置, 例如圖表標題除了可用 px.scatter() 的 title 參數設定外, 也可以用update_layout() 方法的 title 參數設定. 可傳入之參數如下表 :
| update_layout() 方法的參數 | 說明 |
|---|---|
| title | 設定圖表標題,可使用字串或字典格式(含位置、字型、大小)。 |
| xaxis | 設定 X 軸的屬性,如標題、範圍、格線等。 |
| yaxis | 設定 Y 軸的屬性,如標題、範圍、格線等。 |
| legend | 設定圖例的顯示位置、字型、方向等。 |
| margin | 設定圖表邊界(top、bottom、left、right)間距。 |
| width / height | 設定圖表寬度與高度(單位:像素)。 |
| font | 設定整張圖表的預設字型(大小 size、樣式 family、顏色 color)。 |
| paper_bgcolor | 設定整張圖的背景顏色。 |
| plot_bgcolor | 設定圖表繪圖區的背景顏色。 |
| template | 套用預設樣式主題,例如 'plotly'、'ggplot2'、'seaborn' 等。 |
| hovermode | 設定滑鼠懸停時的顯示方式,如 'x unified'、'closest' 等。 |
其中色彩相關參數 (plot_bgcolor, paper_bgcolor, font 的 color) 可用顏色名稱字串例如 'white', 16 進位色碼字串例如 '#FFFFFF', 或 RGB 色碼字串 'rgb(255,255,255)' 表示.
例如 :
測試 4 : 顯示 Plotly 生成的散布圖 (4) [看原始碼]
# st-plotly-test-4.py
import streamlit as st
import plotly.express as px
import pandas as pd
# 繪圖的資料
df=pd.DataFrame({
'weight': [49, 65, 53, 45, 56, 47, 52, 61],
'height': [159, 177, 156, 163, 164, 158, 166, 171]
})
# 建立 Figure 物件
fig=px.scatter(df, x='weight', y='height')
fig.update_layout(
title=dict(
text='體重 vs 身高 散佈圖',
x=0.4, # 標題位置 (0=左, 1=右)
font=dict(size=20, color='blue')
),
xaxis=dict(title='體重 (kg)', range=[40, 70], showgrid=True),
yaxis=dict(title='身高 (cm)', range=[150, 180], showgrid=True),
legend=dict(x=0.8, y=1),
width=700,
height=500,
margin=dict(l=50, r=50, t=80, b=50),
plot_bgcolor='white',
paper_bgcolor='lightgray',
font=dict(family='Microsoft JhengHei', size=14),
hovermode='closest'
)
fig.update_traces(marker=dict(size=10, color='blue'))
# 在 Streamlit 顯示圖表
st.plotly_chart(fig)
此例使用 update_layout() 設定了圖表的外觀樣式 (包含標題, 背景, 網格等), 結果如下 :
下面範例是用 Plotly 繪製折線圖 :
測試 5 : 顯示 Plotly 生成的折線圖 [看原始碼]
# st-plotly-test-2.py
import streamlit as st
import plotly.express as px
import pandas as pd
# 繪圖的資料
df=pd.DataFrame({
'x': [1, 2, 3, 4, 5, 6, 7, 8],
'y': [10, 15, 13, 17, 20, 18, 25, 22]
})
# 建立 Figure 物件
fig=px.line(
df,
x='x',
y='y',
title='Plotly 繪製折線圖',
markers=True # 標示資料點
)
fig.update_layout(xaxis_title='X 軸', yaxis_title='Y 軸')
# 在 Streamlit 顯示圖表
st.plotly_chart(fig)
結果如下 :
# st-plotly-test-2.py
import streamlit as st
import plotly.express as px
import pandas as pd
# 繪圖的資料
df=pd.DataFrame({
'月份': ['一月', '二月', '三月', '四月', '五月'],
'今年營收': [120000, 135000, 99000, 150000, 170000],
'去年營收': [110000, 125000, 95000, 145000, 160000]
})
# 將寬表格式轉為長表格式方便繪圖
df_melted=df.melt(id_vars='月份', var_name='年度', value_name='營收')
# 建立 Figure 物件
fig=px.bar(
df_melted,
x='月份',
y='營收',
color='年度',
barmode='group',
title='今年與去年營收比較'
)
# 在 Streamlit 顯示圖表
st.plotly_chart(fig)
結果如下 :
比起 Matplotlib 需要計算直條的左右偏移, 直接支援 grouped 長條圖真是方便啊!





沒有留言 :
張貼留言