作者介绍
莲石东路@乌森
心之所向,无界成长。从底层架构到应用实战,聊聊炼数成金背后的故事。
持续更新数据治理、数据科学、数据可视化、空间计算系列文章。
“数据人创作者联盟” 成员
上一篇介绍了python数据可视化的Dash模块,演示了如何生成静态图表,本篇进入交互式图表部分。用Dash构建一个交互式数据可视化应用只需要两样东西,交互控件和回调函数。
01 交互控件
dash在其官方依赖库dash_core_components中内置了众多常见网页小部件,是我们实现交互式所依托的重要元素。
from dash import Dash
import dash_core_components as dcc
import dash_html_components as html
app = Dash()
app.layout = html.Div([
html.Label('单选下拉菜单'),
html.Br(),
dcc.Dropdown(
options=[
{'label': 'beijing', 'value': 'BJ'},
{'label': 'shanghai', 'value': 'SH'} ],
value='BJ' # 默认选中),
html.Label('多选下拉菜单'),
html.Br(),
dcc.Dropdown(options=[
{'label': 'beijing', 'value': 'BJ'},
{'label': 'shanghai', 'value': 'SH'} ],
value=['BJ', 'SH'],
multi=True # 是否多选
),
html.Label('单选按钮'),html.Br(),
dcc.RadioItems(
options=[
{'label': 'beijing', 'value': 'BJ'},
{'label': 'shanghai', 'value': 'SH'}
],
value='BJ'
),
html.Label('复选按钮'),
html.Br(),
dcc.Checklist(
options=[
{'label': 'beijing', 'value': 'BJ'},
{'label': 'shanghai', 'value': 'SH'} ],
value=['BJ', 'SH']
),
html.Label('文本输入框'),
html.Br(),
dcc.Input(
value='BJ',
type='text'
),
html.Br(),
html.Label('滑动块'),
html.Br(),
dcc.Slider(
min=0,
max=9,
marks={i: 'Label {}'.format(i) if i == 1 else str(i) for i in range(1, 6)}, # 标记value=5, # 默认值
),
], style={'columnCount': 1})
if __name__ == '__main__':
app.run_server()
02 回调函数
dash高度封装了react.js,我们可以不用编写js代码即可完成前端与后端之间的异步交互。
from dash import Dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
app = Dash()
province2city_dict = {
'四川省': '成都市',
'陕西省': '西安市',
'广东省': '广州市'}
app.layout = html.Div(
[
html.H1('根据省名查询省会城市:'),
html.Br(),
dcc.Dropdown(
id='province', # 第一个id,输入的地方
options=[
{'label': '四川省', 'value': '四川省'},
{'label': '陕西省', 'value': '陕西省'},
{'label': '广东省', 'value': '广东省'}
],
value='四川省'
),
html.P(id='city') # 第二个id,输出的地方]
)
# 定义了哪个输入对应哪个输出
def province2city(province):
return province2city_dict[province]
if __name__ == '__main__':
app.run_server()
03 交互式图表
有了交互控件和回调函数的知识,将两者结合起来,我们可以构建一个交互式的图表。例子如下:
import pandas as pd
import numpy as np
from dash import Dash, dependencies
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
app = Dash()
# 数据载入
df = pd.read_csv('https://raw.githubusercontent.com/ffzs/dataset/master/insurance.csv')
app.layout = html.Div([
html.Div([
html.Label('Gender'),
html.Div([
dcc.Dropdown( # 功能性组件,设定id值作为标签关联callback函数中的标签
id='gender',
options=[{'label': i, 'value': i} for i in ['female', 'male']],
value='female'),
]),
html.Label('Color'),
html.Div([
dcc.Dropdown(
id='color',
options=[{'label': i, 'value': i} for i in ['region', 'smoker', 'children']],
value='region'),
]),
]),
html.Div([
dcc.Graph(id='scatter') # 关联graph
])
])
# 对callback函数进行设置,与上面的对应,将数据return回对应id的Graph
@app.callback(
dependencies.Output('scatter', 'figure'),
[dependencies.Input('gender','value'), dependencies.Input('color','value')]
)
def update_scatter(value_gender, value_color):
grouped = df.groupby('sex') # 以性别分组
data = grouped.get_group(value_gender) # 获取选取的性别为变量
color_class = pd.Categorical(data[value_color]) # 将颜色分类数据明确化
s = [(np.sqrt(i)+2) for i in data['age']] # 将年龄数据开方用大小表示用以区别年龄大
小
trace = go.Scatter(
x=data["bmi"],
y=data["charges"],
mode='markers',
marker=dict(
size=s,
sizemode='diameter',
sizeref=0,
color=color_class.codes,
colorscale='Earth'
)
)
layout = go.Layout(margin=dict(l=20, r=20, t=0, b=30))
fig = go.Figure(data=[trace], layout=layout)
return fig
if __name__ == '__main__':
app.run_server() # 运行app
发表评论 取消回复