2025年6月16日 星期一

Streamlit 學習筆記 : 展示 Altair 生成之圖表

終於來到這波 Streamlit 密集學習月的最後一站 : 輸出 Altair 繪製的圖片. 與 Bokeh 一樣我之前也只是有聽過這套件卻從未用過, 所以花了兩三天先做了初步的測試, 紀錄在下面三篇筆記中 :


本系列所有測試文章參考 :


Streamlit 提供 st.altair_chart() 函式來輸出 Altair 繪製的圖表, 其參數結構如下 :

st.altair_chart(figure, use_container_width=True, theme="streamlit", tooltip=True)


參數名稱 說明
chart Altair 的圖表物件 Chart(通常由 alt.Chart() 建立)
use_container_width 布林值,是否讓圖表自動填滿容器寬度,預設為 True
theme 指定要套用的主題例如 "streamlit""none"(預設)
tooltip 布林值,是否啟用互動工具提示,預設為 True


必要參數為 Altair 的圖表物件 Chart, 只要將 Chart 物件傳給 st.altair_chart() 即可將圖片顯示在 Streamlit 的網頁中. 


1. 折線圖 : 

Altair 的折線圖繪製方法是 mark_line(), 例如 :


測試 1-1 : 輸出 Altair 折線圖 (1) [看原始碼] 

# st-altair-line-test-1-1.py
import streamlit as st
import altair as alt
import pandas as pd

# 建立資料
df=pd.DataFrame({
    'x': [0, 1, 2, 3, 4, 5],    # x 軸資料
    'y': [-5, -2, 6, 12, 4, 9]  # y 軸資料
    })
# 建立繪製折線圖的 Chart 物件
chart=alt.Chart(df).mark_line(
    color='red',   # 線的顏色
    strokeWidth=4  # 線的粗細 (預設 2)    
    ).encode(
    x=alt.X('x', title='X 軸'),   # 設定 X 軸標籤
    y=alt.Y('y', title='Y 軸'),   # 設定 Y 軸標籤
    tooltip=['x', 'y']  # 資料點工具提示
    ).properties(
    width=400,   # 圖片寬 (px)
    height=300,  # 圖片高 (px)
    title='Altair 折線圖',  # 圖片標題
    )
# 在 Streamlit 顯示圖表
st.altair_chart(chart, use_container_width=False)

此例因為指定了圖片尺寸, 所以要把 use_container_width 設為 False, 否則會放大到容器寬度, 結果如下 : 



下面範例設定線段樣式為虛線與背景色 : 


測試 1-2 : 輸出 Altair 折線圖 (2) [看原始碼] 

# st-altair-line-test-1-2.py
import streamlit as st
import altair as alt
import pandas as pd

# 建立資料
df=pd.DataFrame({
    'x': [0, 1, 2, 3, 4, 5],    # x 軸資料
    'y': [-5, -2, 6, 12, 4, 9]  # y 軸資料
    })
# 建立繪製折線圖的 Chart 物件
chart=alt.Chart(df).mark_line(
    color='rgba(0, 0, 255, 0.5)',   # 線的顏色
    strokeWidth=4  # 線的粗細 (預設 2)    
    ).encode(
    x=alt.X('x', title='X 軸'),   # 設定 X 軸標籤
    y=alt.Y('y', title='Y 軸'),   # 設定 Y 軸標籤
    tooltip=['x', 'y']  # 資料點工具提示
    ).properties(
    width=400,   # 圖片寬 (px)
    height=300,  # 圖片高 (px)
    title='Altair 折線圖',  # 圖片標題
    ).configure_view(
    fill='lightyellow'  # 僅繪圖區背景色
    ).configure_title(
    anchor='end',  # 靠右
    fontSize=16,
    fontWeight='bold',
    color='blue',
    offset=15
    )
# 在 Streamlit 顯示圖表
st.altair_chart(chart, use_container_width=False)

結果如下 : 




2. 散布圖 : 

Altair 的散布圖繪製方法是 mark_point(), 例如 :


測試 2-1 : 輸出 Altair 散布圖 (1) [看原始碼] 

# st-altair-point-test-1.py
import streamlit as st
import altair as alt
import pandas as pd

# 建立資料
df=pd.DataFrame({
    'x': [0, 1, 2, 3, 4, 5],    # x 軸資料
    'y': [-5, -2, 6, 12, 4, 9]  # y 軸資料
    })
# 建立繪製折線圖的 Chart 物件
chart=alt.Chart(df).mark_point(
    filled=True,   # 填滿為實心圓點
    size=200,   # 平方像素面積
    color='red',  # 填滿顏色
    stroke='#0000FF',   # 邊框顏色
    strokeWidth=2,  # 邊框
    strokeOpacity=0.5  # 邊框透明度
    ).encode(
    x='x',
    y='y',
    tooltip=['x', 'y']   # 資料點工具提示
    ).properties(
    width=400,   # 圖片寬 (px)
    height=300,  # 圖片高 (px)
    title='Altair 散布圖'  # 圖片標題
    )
# 在 Streamlit 顯示圖表
st.altair_chart(chart, use_container_width=False)

結果如下 : 



下面範例是利用分類欄位讓不同類別的資料點顯示不同之標記符號 (自動配色) : 


測試 2-2 : 輸出 Altair 散布圖 (2) [看原始碼] 

# st-altair-point-test-1.py
import streamlit as st
import altair as alt
import pandas as pd

# 建立資料
df=pd.DataFrame({
    'x': [0, 1, 2, 3, 4, 5],    # x 軸資料
    'y': [-5, -2, 6, 12, 4, 9],  # y 軸資料
    'label': ['A', 'B', 'A', 'B', 'A', 'B']  # 資料分類  
    })
# 建立繪製折線圖的 Chart 物件
chart=alt.Chart(df).mark_point(
    filled=True,   # 填滿為實心圓點
    size=200,   # 平方像素面積
    color='yellow',  # 填滿顏色
    stroke='navy'
    ).encode(
    x=alt.X('x', title='X 軸'),   # 設定 X 軸標籤
    y=alt.Y('y', title='Y 軸'),   # 設定 Y 軸標籤
    shape='label',  # 資料點的圖形分類欄位
    color='label',  # 顏色根據 label 分類
    tooltip=['x', 'y']   # 資料點工具提示
    ).properties(
    width=400,   # 圖片寬 (px)
    height=300,  # 圖片高 (px)
    title='Altair 散布圖'  # 圖片標題
    ).configure_view(
    fill='lightyellow'  # 僅繪圖區背景色
    )
st.altair_chart(chart, use_container_width=False)

結果如下 :




3. 長條圖 : 

Altair 的長條圖繪製方法是 mark_bar(), 例如 :


測試 3-1 : 輸出 Altair 長條圖 (單組垂直) [看原始碼] 

# st-altair-bar-test-1.py
import streamlit as st
import altair as alt
import pandas as pd

# 建立資料
df=pd.DataFrame({
    '月份': ['一月', '二月', '三月', '四月', '五月'],
    '營收': [120000, 135000, 99000, 150000, 170000]
    })
# 建立繪製折線圖的 Chart 物件
chart=alt.Chart(df).mark_bar(
    color='cyan',  # 設定長條顏色
    size=30,   # 設定長條寬度 px
    stroke='navy'   # 設定邊框顏色
    ).encode(
    x=alt.X('月份', sort=['一月', '二月', '三月', '四月', '五月']),   # 列舉 X 軸順序
    y='營收',
    ).properties(
    width=400,   # 圖片寬 (px)
    height=300,  # 圖片高 (px)
    title='Altair 長條圖'  # 圖片標題
    )
st.altair_chart(chart, use_container_width=False)

結果如下 : 




在 encode() 中把 X, Y 軸顛倒就會得到水平長條圖, 例如 :


測試 3-2 : 輸出 Altair 長條圖 (單組水平) [看原始碼] 

# st-altair-bar-test-2.py
import streamlit as st
import altair as alt
import pandas as pd

# 建立資料
df=pd.DataFrame({
    '月份': ['一月', '二月', '三月', '四月', '五月'],
    '營收': [120000, 135000, 99000, 150000, 170000]
    })
# 建立繪製折線圖的 Chart 物件
chart=alt.Chart(df).mark_bar(
    color='cyan',  # 設定長條顏色
    size=30,   # 設定長條寬度 px
    stroke='navy'   # 設定邊框顏色
    ).encode(
    y=alt.Y('月份', sort=['一月', '二月', '三月', '四月', '五月']),   # 列舉 Y 軸順序
    x='營收',
    ).properties(
    width=400,   # 圖片寬 (px)
    height=300,  # 圖片高 (px)
    title='Altair 長條圖'  # 圖片標題
    )
st.altair_chart(chart, use_container_width=False)

結果如下 :




下面範例是繪製兩組資料的群組式垂直長條圖 :


測試 3-3 : 輸出 Altair 群組式長條圖 (雙組垂直) [看原始碼] 

# st-altair-bar-test-3.py
import streamlit as st
import altair as alt
import pandas as pd

# 原始資料
x=['一月', '二月', '三月', '四月', '五月']
y1=[120000, 135000, 99000, 150000, 170000]
y2=[100000, 125000, 87000, 140000, 160000]

# 將原始資料轉成長格式的 DataFrame
df=pd.DataFrame({
    '月份': x * 2,
    '營收': y1 + y2,
    '類別': ['今年'] * len(x) + ['去年'] * len(x)
    })

# 建立群組長條圖
chart=alt.Chart(df).mark_bar().encode(
    x=alt.X(
        '月份:N',
        title='月份',
        sort=['一月', '二月', '三月', '四月', '五月'],
        axis=alt.Axis(labelAngle=0) # 軸刻度文字旋轉 0 度=水平
        ),
    y=alt.Y('營收:Q', title='營收金額 (元)'),
    color=alt.Color('類別:N', title='類別'),
    xOffset='類別:N',  # 依照指定欄位群組化顯示長條
    tooltip=['月份', '類別', '營收']
    ).properties(
    width=400,
    height=300,
    title='今年與去年每月營收比較'
    )   
st.altair_chart(chart, use_container_width=False)

注意此例使用 alt.Axis(labelAngle=0) 將 X 軸標籤角度設為 0 (水平), 群組化關鍵是用 xOffset 參數設定分組欄位名稱, 結果如下 :



繪製群組式水平長條圖只要將 encode() 裡的 x, y 軸顛倒, 而且用 yOffset 參數設定 Y 軸分組欄位名稱即可 : 


測試 3-4 : 輸出 Altair 群組式長條圖 (雙組水平) [看原始碼] 

# st-altair-bar-test-3.py
import streamlit as st
import altair as alt
import pandas as pd

# 原始資料
df=pd.DataFrame({
    '月份': ['一月', '二月', '三月', '四月', '五月'],
    '今年': [120000, 135000, 99000, 150000, 170000],
    '去年': [100000, 125000, 87000, 140000, 160000]
    })

# 將原始資料轉成長格式的 DataFrame
df=df.melt(
    id_vars=['月份'],   # 保持不變的欄位 (其他欄位要被融化)
    value_name='營收',  # 融化後新的數值欄位名稱
    var_name='類別'     # 要新增的分類欄位名稱
    )

# 建立群組長條圖
chart=alt.Chart(df).mark_bar().encode(
    y=alt.Y(
        '月份:N',
        title='月份',
        sort=['一月', '二月', '三月', '四月', '五月'],
        axis=alt.Axis(labelAngle=0) # 軸刻度文字旋轉 0 度=水平
        ),
    x=alt.X('營收:Q', title='營收金額 (元)'),
    color=alt.Color('類別:N', title='類別'),
    yOffset='類別:N',  # 依照指定欄位群組化顯示長條
    tooltip=['月份', '類別', '營收']
    ).properties(
    width=400,
    height=300,
    title='今年與去年每月營收比較'
    )   
st.altair_chart(chart, use_container_width=False)

此例改用 df.melt() 將原始寬格式 DataFrame 改成長格式, 結果如下 :




OK, 歷經一個半月的測試, 終於把 Streamlit 的基本功能學完了, 未來應用時如果有發現遺漏的或新的用法再來補充. 不過接下來會把 Streamlit 用在機器學習/深度學習的再整理與測試上. 

沒有留言 :