本文示例程式碼與資料已上傳至我的
Github
倉庫https://github.com/CNFeffery/DataScienceStudyNotes
1 簡介
這是我的新系列教程Python+Dash快速web應用開發的第一期,我們都清楚學習一個新工具需要一定的動力,那麼為什麼我要專門為Dash
製作一個系列教程呢?
Dash
是一個高效簡潔的Python
框架,建立在Flask
、Poltly.js
以及React.js
的基礎上,設計之初是為了幫助前端知識匱乏的資料分析人員,以純Python
程式設計的方式快速開發出互動式的資料視覺化web應用。
Dash
已經過數年的迭代發展,早期的Dash
我也體驗過,但當時還比較簡陋,很多問題亟待解決,因此並沒有引起我的多大注意。
但隨著近一兩年的高速發展和積極更新迭代,現階段的Dash
已經是一個相當成熟的框架,且其功能已經豐富到不僅僅可以用來開發線上資料視覺化作品,即使是輕量級的資料儀表盤、BI應用,甚至是搭建文件說明、部落格或常規的網站,都駕馭得住,配合豐富的第三方擴充,只會Python
的你可以開發出相當精美正式的web應用。
而關於Dash
的像樣的中文教程幾乎沒有(其實英文教程也沒多少?),有的也大多隻是在照搬官方文件,因此類似之前寫作完成反響不錯的geopandas教程那樣,我來寫一個看得過去的系列教程吧~下面開始我們的Dash
之旅吧!
2 Dash中的基礎概念
在學習Dash
的一開始,我們需要對Dash
的若干基礎概念進行了解,首先我們來從頭開始搭建Dash
環境,因為主要是面向資料分析處理人員,所以我推薦使用conda
進行環境管理,參考下列命令即可完成環境的初始化:
conda create -n dash-dev python=3.7 -y
conda activate dash-dev
pip install dash -U
上述程式碼執行完成後,你就已經建立好最基本的Dash
執行所需環境了,你可以建立程式碼如下的py
指令碼並執行(推薦使用pycharm
、vscode
等工具進行Dash
開發):
app1.py
import dash
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.H1('第一個Dash應用!')
if __name__ == '__main__':
app.run_server()
執行上述指令碼之後,一切正常的話,按照提示點選進對應網址會看到如下內容:
至此我們就完成了Dash
環境的搭建,下面我們來了解Dash
應用中的一些基礎概念:
2.1 用layout設計頁面內容
一個web應用的關鍵之一在於其前端所呈現的頁面內容,在Dash
中我們通過對其layout
屬性進行定義,從而自由設計頁面內容。
在前面的app1.py
中,我們設定了app.layout = html.H1('第一個Dash應用!')
,這裡的html
即開頭匯入的dash_html_components
,它是dash
的自帶依賴庫,用於在Dash
應用中定義常見的html
元素,就像前面用到的H1
對應一級標題,即<h1></h1>
標籤。
而每個html.XX
物件,其接收的第一個位置上的引數都是children
,它用於表示對應html
標籤所包裹的內容,譬如上文的'第一個Dash應用!'
,也可以通過傳入多元素列表或進行多層巢狀,從而構建結構更復雜的頁面內容,就像下面的例子一樣:
app2.py
import dash
import dash_html_components as html
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1('標題1'),
html.H1('標題2'),
html.P(['測試', html.Br(), '測試']),
html.Table(
html.Tr(
[
html.Td('第一列'),
html.Td('第二列')
]
)
)
]
)
if __name__ == '__main__':
app.run_server()
而除了常見的html
元素之外,Dash
還在其官方依賴庫dash_core_components
中內建了眾多常見網頁小部件,是我們實現互動式所依託的重要元素,就像下面的例子一樣我們利用其Dropdown
部件建立出一個下拉選擇部件:
app3.py
import dash
import dash_html_components as html
import dash_core_components as dcc
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1('下拉選擇'),
html.Br(),
dcc.Dropdown(
options=[
{'label': '選項一', 'value': 1},
{'label': '選項二', 'value': 2},
{'label': '選項三', 'value': 3}
]
)
]
)
if __name__ == '__main__':
app.run_server()
Dash
與plotly
既然“師出同門”,自然已經相互打通,我們同樣可以非常輕鬆的在網頁中插入資料視覺化的內容,這裡我們使用到plotly.express
,它簡化了諸多plotly
圖表的建立過程,將建立好的圖表物件作為figure
引數傳入dcc.Graph()
中即可:
app4.py
import dash
import dash_html_components as html
import dash_core_components as dcc
import plotly.express as px
app = dash.Dash(__name__)
fig = px.scatter(x=range(10), y=range(10))
app.layout = html.Div(
[
html.H1('嵌入plotly圖表'),
dcc.Graph(figure=fig)
]
)
if __name__ == '__main__':
app.run_server()
除了上述的幾個官方Dash
依賴庫以外,還有很多優秀的第三方庫都可以幫助我們快速建立出效果驚人的前端內容,關於這部分的詳細內容我將會在本系列之後的文章中分主題詳細介紹,敬請期待。
2.2 用callback實現互動
Dash
最大的優點之一就是其高度封裝了React.js
,使得我們無需編寫js
程式碼即可實現前端與後端之間的非同步互動,為了實現這一步,我們需要使用到dash.dependencies
中的Input
與Output
,再配合自定義回撥函式來實現所需互動功能。
舉一個非常簡單的例子:我們設計一個web頁面,其中有一個下拉選項部件,當我們下拉選取到某個選項值對應的省份時,其下方列印出對應的省會城市:
app5.py
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
app.layout = html.Div(
[
html.H1('根據省名查詢省會城市:'),
html.Br(),
dcc.Dropdown(
id='province',
options=[
{'label': '四川省', 'value': '四川省'},
{'label': '陝西省', 'value': '陝西省'},
{'label': '廣東省', 'value': '廣東省'}
],
value='四川省'
),
html.P(id='city')
]
)
province2city_dict = {
'四川省': '成都市',
'陝西省': '西安市',
'廣東省': '廣州市'
}
@app.callback(Output('city', 'children'),
Input('province', 'value'))
def province2city(province):
return province2city_dict[province]
if __name__ == '__main__':
app.run_server()
在互動操作的時候檢視後臺可以看到,每一次點選都在進行與後臺的非同步通訊,我們整個應用的頁面並沒有重新整理,如果不用Dash
,你就得書寫相應的js
語句,較為繁瑣:
而Dash
目前已經支援多輸入多輸出的回撥函式書寫方式,以及阻止初次回撥、基於表單提交狀態的回撥等諸多特性,理論上你可以建立出任何形式的頁面互動行為,這些內容我們都會在之後的系列文章中詳細教授給大家。
2.3 監聽圖表互動式選擇行為
Dash
與plotly
的高度耦合,還體現在其可以監聽針對plotly
圖表的懸浮、選擇、框選等行為,廣泛適用於plotly
中的大量常規圖表與地圖,這一點懂的朋友應該都明白,藉助這個特性,我們可以建立出互動能力強大的web應用,就像我下面的這個典型的例子:
app6.py
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
app = dash.Dash(__name__)
fig = px.scatter(x=range(10), y=range(10), height=400)
fig.update_layout(clickmode='event+select') # 設定點選模式
app.layout = html.Div(
[
dcc.Graph(figure=fig, id='scatter'),
html.Hr(),
html.Div([
'懸浮事件:',
html.P(id='hover')
]),
html.Hr(),
html.Div([
'點選事件:',
html.P(id='click')
]),
html.Hr(),
html.Div([
'選擇事件:',
html.P(id='select')
]),
html.Hr(),
html.Div([
'框選事件:',
html.P(id='zoom')
])
]
)
# 多對多的回撥函式
@app.callback([Output('hover', 'children'),
Output('click', 'children'),
Output('select', 'children'),
Output('zoom', 'children'),],
[Input('scatter', 'hoverData'),
Input('scatter', 'clickData'),
Input('scatter', 'selectedData'),
Input('scatter', 'relayoutData')])
def listen_to_hover(hoverData, clickData, selectedData, relayoutData):
return str(hoverData), str(clickData), str(selectedData), str(relayoutData)
if __name__ == '__main__':
app.run_server()
可以看到,我們監聽到的懸浮、點選、選擇以及框選四種行為對應傳回的特徵資料:
而這方面內容,我也會在之後的系列文章中進行非常詳實的介紹?~
我們接下來的系列文章就會圍繞上述基礎概念,以及多頁面應用、外部css、js的引入、Dash應用的部署釋出等還未提及的重要內容進行詳細介紹,以幫助廣大使用Python
的讀者朋友使用最少的前端知識,建立出優秀的web應用,方便日常的工作學習生產生活,敬請期待!
以上就是本文的全部內容,歡迎在評論區與我進行討論~