使用 Dash 庫構建可互動的資料展示 Web 應用

倒地發表於2024-05-31

概述

Dash 是一個 Python 庫,脫胎於 Plotly,可以很方便構建可互動的資料展示 Web 應用。

快速入門

安裝

pip install dash

基本結構

一個 Hello World 示例,可以看到 dash app 是如何建立的:

from dash import Dash, html

app = Dash()
app.layout = [html.Div(children='Hello World')]

if __name__ == '__main__':
    app.run(debug=True)

可見,

  • app = Dash() 建立一個 app 例項
  • app.run() 執行這個 app 例項
  • app.layout 列表可以進行賦值,能直接將 html 元素放進去

要自定義頁面元素,往 app.layout 列表塞東西即可。

Table 和 Graph

假設現在有一個 pandas 表格,

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminder2007.csv')

可以透過 dash_table.DataTabledoc.Graph 繪製表格和柱狀圖。

from dash import dash_table, dcc
import plotly.express as px
···
app.layout = [
    ···
    dash_table.DataTable(data=df.to_dict('records'), page_size=10),
    dcc.Graph(figure=px.histogram(df, x='continent', y='lifeExp', histfunc='avg'))
]

Callback 控制

單選框 dcc.RadioItems。需要傳入一個獨一無二的 id

dcc.RadioItems(options=['pop', 'lifeExp', 'gdpPercap'], value='lifeExp', id='controls-and-radio-item')

目標是給這個單選框綁一個 Callback,控制柱狀圖的顯示。柱狀圖控制元件也要傳入 id

dcc.Graph(figure={}, id='controls-and-graph')

Callback 使用修飾器 callback 進行定義。修飾器會很直觀地定義:

  • 用哪個 id 的控制元件的元素作為輸入
  • 對哪個 id 的控制元件的元素進行輸出
from dash import callback, Output, Input

@callback(
    Output(component_id='controls-and-graph', component_property='figure'),
    Input(component_id='controls-and-radio-item', component_property='value'),
)
def update_graph(col_chosen):
    fig = px.histogram(df, x='continent', y=col_chosen, histfunc='avg')
    return fig

不需要額外的繫結,給函式寫好 callback 修飾器即可。

一些常用操作

這一節會省略 import 操作。

藉助 Div 避免貼邊

dash.html.Div 是 html5 <div> 的封裝,可以傳入 style 引數。

可以不再向 app.layout 傳入 List,而是傳入一個 html.Div 物件。所需元素放到省略號內就行。

app.layout = html.Div(
    [
        ···
    ],
    style={
        'margin': 'auto',
        'max-width': '80%',
    },
)

Markdown

直接寫入 Markdown 語法文段:

dcc.Markdown(
    '''
# My first try
'''
)

結合 html.Div 使用可以避免貼住左邊。

顯示圖片

本節參考

第一種方法,使用 html5 <img> 的封裝 html.Img

# 傳入圖片路徑
image_path = 'assets/my-image.png'
html.Img(src=image_path)
# 或者使用 base64
import base64

image_path = 'assets/my-image.png'
def b64_image(image_filename):
  with open(image_filename, 'rb') as f:
      image = f.read()
return 'data:image/png;base64,' + base64.b64encode(image).decode('utf-8')

html.Img(src=b64_image(image_path))

第二種方法,藉助 plotly.express。優勢是可以傳入 numpy 矩陣。

dcc.Graph(
    figure=px.imshow(
        cv2.imread("test.jpg",)[..., [2, 1, 0]]  # BGR -> RGB
    )
)

cv2 讀取的通道順序預設是 BGR。

from PIL import Image

dcc.Graph(
    figure=px.imshow(Image.open("test,jpg"))
)

高階自定義

懸停文字自定義

參考來源

使用 .update_traces() 設定 hovertemplate,自定義節點的懸停文字。

import plotly.express as px

fig = px.scatter(df_2007, x="gdpPercap", y="lifeExp", log_x=True, color='continent')

fig.update_traces(hovertemplate='GDP: %{x} <br>Life Expectancy: %{y}')
fig.update_traces(hovertemplate=None, selector={'name':'Europe'}) # revert to default hover

相關文章