plotly-dash

Dash Based On Plotly

个人分类: python

<article class="baidu_pl" style="box-sizing: inherit; outline: 0px; display: block; position: relative; padding-top: 16px; color: rgba(0, 0, 0, 0.75); font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: common-ligatures; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangjianjaEE/article/details/76572327

官方文档:https://plot.ly/dash

介绍

Dash is a productive Python framework for building web applications.

Written on top of Flask, Plotly.js, and React.js, Dash is ideal for building data visualization apps with highly custom user interfaces in pure Python. It's particuarly suited for anyone who works with data in Python.

Through a couple of simple patterns, Dash abstracts away all of the technologies and protocols that are required to build an interactive web-based application. Dash is simple enough that you can bind a user interface around your Python code in an afternoon.

Dash apps are rendered in the web browser. You can deploy your apps to servers and then share them through URLs. Since Dash apps are viewed in the web browser, Dash is inherently cross-platform and mobile ready.

There is a lot behind the framework. To learn more about how it is built and what motivated dash, watch our talk from Plotcon below or read our announcement letter.

Dash is an open source library, released under the permissive MIT license. Plotly develops Dash and offers a platform for deploying, orchestrating, and permissioning dash apps in an enterprise environment

安装

In your terminal, install several dash libraries. These libraries are under active development, so install and upgrade frequently. Python 2 and 3 are supported.

pip install dash==0.17.7  # The core dash backend
pip install dash-renderer==0.7.4  # The dash front-end
pip install dash-html-components==0.7.0  # HTML components
pip install dash-core-components==0.7.1  # Supercharged components
pip install plotly==2.0.12  # Plotly graphing library used in 

examples

Dash App Layout

Generating HTML with Dash

Dash apps are composed of two parts. The first part is the "layout" of the app and it describes what the application looks like. The second part describes the interactivity(内部联系) of the application.

Dash provides Python classes for all of the visual components of the application. We maintain a set of components in the dash_core_components and the dash_html_components library but you can also build your own with JavaScript and React.js.

To get started, create a file named app.py with the following code:

app.py

# coding=UTF-8
'''
@Author: zhangjian
@File: app.py
@Date:17-8-1 上午9:33
'''
'''
Dash 示例程序
'''
import dash
import dash_core_components as dcc
import dash_html_components as html
# 实例化一个Dash对象
app = dash.Dash()
'''
dash页面的布局结构为:
1 整个页面是一个div
2 div内设定一个h1型号的标题
3 div内包含一个子div,且内容为一行文本

'''
app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),
    html.Div(children='''
        Dash: A web application framework for Python.
    '''),
    dcc.Graph(
        # 唯一标识该图形,此属性并不显示在页面
        id='example-graph',
        # 图形的具体内容
        figure={
            # data是key,值为元素为字典的列表,即图形的具体数据,
            # 其中x为横轴数据链,y为与x相对应的纵轴数据链,
            # type为图形的类型,name为图形标识
            'data': [
                {'x': [1, 2, 3], 'y': [4, 10, 2], 'type': 'bar', 'name': 'AAPL'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': 'IBM'},
            ],
            # 图形的标题
            'layout': {
                'title': 'Dash Data Visualization'
            }
        }
    )
])
# 入口方法
if __name__ == '__main__':
    app.run_server(debug=True)

查看运行结果:
http://localhost:8050
如图:

这里写图片描述

Notes

  1. The layout is composed of a tree of “components” like html.Div and dcc.Graph.
  2. The dash_html_components library has a component for every HTML tag.it’s so powerful! The html.H1(children=’Hello Dash’) component generates a < h 1>Hello Dash< /h 1>HTML element in your application.
  3. Not all components are pure(单纯的) HTML. The dash_core_components describe higher-level components that are interactive and are generated with JavaScript, HTML, and CSS through the React.js library.
  4. Each component is described entirely through keyword attributes. Dash is declarative(公布的,宣言的): you will primarily(主要地) describe your application through these attributes.
  5. The children property is special. By convention(惯例), it’s always the first attribute which means that you can omit(省略) it: html.H1(children=’Hello Dash’) is the same as html.H1(‘Hello Dash’). Also, it can contain a string, a number, a single component, or a list of components.
  6. The fonts in your application will look a little bit different than what is displayed here. This application is using a custom CSS stylesheet to modify the default styles of the elements. You can learn more in the css tutorial, but for now you can add app.css.append_css({“external_url”: “https://codepen.io/chriddyp/pen/bWLwgP.css“}) to your file to get the same look and feel of these examples.
    By default, the items in your layout are arranged(安排) one on top of the other(即上下结构). You can create different arrangements(安排方式) using CSS and stylesheets in the custom layout arrangements in Dash apps tutorial ;
    More about HTML
    The dash_html_components library contains a component class for every HTML tag as well as keyword arguments for all of the HTML arguments.
    Let’s customize the text in our app.py by modifying the inline styles of the components:

app.py

(modified by new styles)

# coding=UTF-8
'''
@Author: zhangjian
@File: app.py
@Date:17-8-1 上午9:33
'''
'''
Dash 示例程序
'''
import dash
import dash_core_components as dcc
import dash_html_components as html
# 实例化一个Dash对象
app=dash.Dash()
#css 属性字典
colors={'background': '#111111','text': '#7FDBFF'}
# dash页面的布局结构为:
# 1 整个页面是一个div
# 2 div内设定一个h1型号的标题
# 3 div内包含一个子div,且内容为一行文本
app.layout = html.Div(style={'backgroundColor': colors['background']},children=[
    html.H1(children='Hello Dash',
            style={
            'textAlign': 'center',
            'color': colors['text']
            }),
    html.Div(children='''
        Dash: A web application framework for Python.
    ''',
             style={
        'textAlign': 'center',
        'color': colors['text']
             }),
    dcc.Graph(
        # 唯一标识该图形,此属性并不显示在页面
        id='example-graph',
        # 图形的具体内容
        figure={
            # data是key,值为元素为字典的列表,即图形的具体数据,
            # 其中x为横轴数据链,y为与x相对应的纵轴数据链,
            # type为图形的类型,name为图形标识
            'data': [
                {'x': [1, 2, 3], 'y': [4, 10, 2], 'type': 'bar', 'name': 'AAPL'},
                {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': 'IBM'},
            ],
            # 图形的标题
            'layout': {
                'title': 'Dash Data Visualization',
                'plot_bgcolor': colors['background'],
                'paper_bgcolor': colors['background'],
                'font': {
                    'color': colors['text']
                }
            }
        }
    )
])
# 附加css样式
app.css.append_css({"external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"})
# 入口方法
if __name__ == '__main__':
    app.run_server(debug=True)

查看运行结果,如图:


这里写图片描述

Notes

In this example, we modified the inline styles of the html.Div and html.H1 components with the style property.

html.H1('Hello Dash', style={'textAlign`': 'center', 'color': '#7FDFF'}) is rendered in the Dash application as < h1 style="text-align: center; color: #7FDFF">Hello Dash< /h1>.

There are a few important differences between the dash_html_components and the HTML attributes:

  1. The style property in HTML is a semicolon-separated string. In Dash, you can just supply a dictionary.

  2. The keys in the style dictionary are camelCased. So, instead of text-align, it’s textAlign.

  3. The HTML class attribute is className in Dash.

  4. The children of the HTML tag is specified through the children keyword argument.
    Besides that, all of the available HTML attributes and tags are available to you within your Python context.

下面的数据源是后续文档中都会用到的,为方便理解后续的代码,提前将其声明出来;
csv格式的数据源
URL:https://gist.githubusercontent.com/chriddyp/cb5392c35661370d95f300086accea51/raw/8e0768211f6b747c0db42a9ce9a0937dafcbd8b2/indicators.csv
列名:Country Name||Indicator Name||Year||Value
如图:

这里写图片描述

Reusable Components

By writing our markup in Python, we can create complex resuable components like tables without switching contexts or languages.

Here's a quick example that generates a Table from a Pandas dataframe. If you don't have Pandas installed, install with pip install pandas.

table.py

# coding=UTF-8
'''
@Author: zhangjian
@File: table.py.py
@Date:17-8-1 上午10:51
'''
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
# 读取csv文件,read_csv()方法返回值类型为dataFrame
df = pd.read_csv(
    'https://gist.githubusercontent.com/chriddyp/'
    'c78bf172206ce24f77d6363a2d754b59/raw/'
    'c353e8ef842413cae56ae3920b8fd78468aa4cb2/'
    'usa-agricultural-exports-2011.csv')
'''
生成表的方法
输入参数:
- dataframe
- 行上限
输出:
将dataframe中的数据转换成表格的形式输出(行数<=行上限)
列表之间可以用“+”连接,表示列表合并,如:[1,'A']+[2]=[1,'A',2]
'''
def generate_table(dataframe, max_rows=10):
    return html.Table(
        # Header
        [html.Tr([html.Th(col) for col in dataframe.columns])] +
        # Body
        [html.Tr([
            html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
        ]) for i in range(min(len(dataframe), max_rows))]
    )
app = dash.Dash()
# 页面布局:
# 1\. 整个页面由一个div构成
# 2\. div有个h4尺寸的标题
# 3\. 标题下面有个表格
app.layout = html.Div(children=[
    html.H4(children='US Agriculture Exports (2011)'),
    generate_table(df)
],style={'background':'gray'}
)
if __name__ == '__main__':
    app.run_server(debug=True)

运行结果如图:


这里写图片描述

More about Visualization

The dash_core_components library includes a component called Graph.

Graph renders(给予) interactive(互动的) data visualizations using the open source plotly.js JavaScript graphing library. Plotly.js supports over 35 chart types and renders charts in both vector-quality SVG and high-performance(高性能) WebGL.

The figure argument in the dash_core_components.Graph component is the same figure argument that is used by plotly.py, Plotly's open source Python graphing library. Check out the plotly.py documentation and gallery to learn more.

graph.py

# coding=utf-8
'''
@Author: zhangjian
@File: graph.py
@Date:17-8-1 上午11:25
'''
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
app = dash.Dash()
#读取csv文件,返回dataframe
df = pd.read_csv(
    'https://gist.githubusercontent.com/chriddyp/' +
    '5d1ea79569ed194d432e56108a04d188/raw/' +
    'a9f9e8076b837d541398e999dcbac2b2826a81f8/'+
    'gdp-life-exp-2007.csv')
'''
页面布局:
'''
app.layout = html.Div([
    # graph组件
    dcc.Graph(
        # 图形唯一标识,不显示在页面
        id='life-exp-vs-gdp',
        figure={
            # 遍历dataframe中的数据,并显示出来
            'data': [
                go.Scatter(
                    x=df[df['continent'] == i]['gdp per capita'],
                    y=df[df['continent'] == i]['life expectancy'],
                    text=df[df['continent'] == i]['country'],
                    mode='markers',
                    opacity=0.7,
                    marker={
                        'size': 15,
                        'line': {'width': 0.5, 'color': 'white'}
                    },
                    name=i
                ) for i in df.continent.unique()
            ],
            'layout': go.Layout(
                xaxis={'type': 'log', 'title': 'GDP Per Capita'},
                yaxis={'title': 'Life Expectancy'},
                margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
                legend={'x': 0, 'y': 1},
                hovermode='closest'
            )
        }
    )
])
if __name__ == '__main__':
    app.run_server()

运行结果如图:


这里写图片描述

Notes

These graphs are interactive and responsive. Hover over points to see their values, click on legend items to toggle traces, click and drag to zoom, hold down shift, and click and drag to pan.

Markdown

While Dash exposes(暴露,曝光) HTML through the dash_html_components library, it can be tedious(乏味的) to write your copy(稿件) in HTML. For writing blocks of text(文本块), you can use the Markdown component in the dash_core_components library.

Core Components

The dash_core_components includes a set a higher-level components like dropdowns, graphs, markdown blocks, and more.

Like all Dash components, they are described entirely declaratively. Every option that is configurable is available as a keyword argument of the component.

Dash ships with supercharged components for interactive user interfaces. A core set of components, written and maintained by the Dash team, is available in the dash-core-components library.

The source is on GitHub at plotly/dash-core-components.

dash_core_components各组件示例用法:

Dropdown(下拉框)

import dash_core_components as dcc

dcc.Dropdown(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': 'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    value='MTL'
)
import dash_core_components as dcc

dcc.Dropdown(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': 'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    multi=True,
    value="MTL"
)

Slider(滑动条)

import dash_core_components as dcc

dcc.Slider(
    min=-5,
    max=10,
    step=0.5,
    value=-3,
)
import dash_core_components as dcc

dcc.Slider(
    min=0,
    max=9,
    marks={i: 'Label {}'.format(i) for i in range(10)},
    value=5,
)

RangeSlider(可选范围的滑动条)

import dash_core_components as dcc

dcc.RangeSlider(
    count=1,
    min=-5,
    max=10,
    step=0.5,
    value=[-3, 7]
)
import dash_core_components as dcc

dcc.RangeSlider(
    marks={i: 'Label {}'.format(i) for i in range(-5, 7)},
    min=-5,
    max=6,
    value=[-3, 4]
)

Input(输入框)
import dash_core_components as dcc

dcc.Input(
    placeholder='Enter a value...',
    type='text',
    value=''
)

Checkboxes(复选框)

import dash_core_components as dcc

dcc.Checklist(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': 'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    values=['MTL', 'SF']
)
import dash_core_components as dcc

dcc.Checklist(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': 'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    values=['MTL', 'SF'],
    labelStyle={'display': 'inline-block'}
)

Radio Items(单选框)
import dash_core_components as dcc

dcc.RadioItems(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': 'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    value='MTL'
)
import dash_core_components as dcc

dcc.RadioItems(
    options=[
        {'label': 'New York City', 'value': 'NYC'},
        {'label': 'Montréal', 'value': 'MTL'},
        {'label': 'San Francisco', 'value': 'SF'}
    ],
    value='MTL',
    labelStyle={'display': 'inline-block'}
)

Markdown

import dash_core_components as dcc

dcc.Markdown('''
Dash and Markdown

Dash supports [Markdown](http://commonmark.org/help).

Markdown is a simple way to write and format text.
It includes a syntax for things like **bold text** and *italics*,
[links](http://commonmark.org/help), inline `code` snippets, lists,
quotes, and more.
''')

Markdown(use Markdown languare to format text )

Dash supports Markdown.
Markdown is a simple way to write and format text. It includes a syntax for things like bold text and italics, links, inline code snippets, lists, quotes, and more.

Graphs

The Graph component shares the same syntax as the open-source plotly.py library. View the plotly.py docs to learn more.

import dash_core_components as dcc
import plotly.graph_objs as go

dcc.Graph(
    figure=go.Figure(
        data=[
            go.Scatter(x=[1, 2, 3], y=[3, 2, 4], mode='lines'),
            go.Scatter(x=[1, 2, 3], y=[4, 1, 5], mode='lines')
        ],
        layout=go.Layout(
            title='Quarterly Results',
            showlegend=False,
            margin=go.Margin(l=20, r=0, t=40, b=20)
        )
    ),
    style={'height': 300},
    id='my-graph'
)

将这些组件测试一下:

dash_core_components.py

#coding=utf-8
'''
@Author: zhangjian
@File: dash_core_component.py
@Date:17-8-1 下午1:16
'''
###############
#Dropdown
###############
# -*- coding: utf-8 -*-
import dash
import dash_html_components as html
import dash_core_components as dcc
app = dash.Dash()
app.layout = html.Div([
    html.Label('Dropdown'),
    # 单选下拉框
    dcc.Dropdown(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value='MTL'
    ),
    html.Label('Multi-Select Dropdown'),
    # 多选下拉框
    dcc.Dropdown(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value=['MTL', 'SF'],
        multi=True
    ),
    html.Label('Radio Items'),
    # 单选框
    dcc.RadioItems(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        value='MTL'
    ),
    html.Label('Checkboxes'),
    # 复选框
    dcc.Checklist(
        options=[
            {'label': 'New York City', 'value': 'NYC'},
            {'label': u'Montréal', 'value': 'MTL'},
            {'label': 'San Francisco', 'value': 'SF'}
        ],
        values=['MTL', 'SF']
    ),
    html.Label('Text Input'),
    # 输入框
    dcc.Input(value='MTL', type='text'),
    html.Label('Slider'),
    # 滑动条
    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': 2})
if __name__ == '__main__':
    app.run_server(debug=True)

运行结果如下:


这里写图片描述

上面各种组件和html中的各种标签实现的功能是一样的,很简单,不再赘述;

API帮助

Dash components are declarative: every configurable aspect of these components is set during instantiation as a keyword argument. Call help in your Python console on any of the components to learn more about a component and its available arguments;

Summary

The layout of a Dash app describes what the app looks like. The layout is a hierarchical tree of components. The dash_html_components library provides classes for all of the HTML tags and the keyword arguments describe the HTML attributes like style, className, and id. The dash_core_components library generates higher-level components like controls and graphs.

Interactivity

The first part of this tutorial covered the layout of Dash apps. The layout of a Dash app describes what the app looks like. It is a hierarchical tree of components. The dash_html_components library provides classes for all of the HTML tags and the keyword arguments describe the HTML attributes like style, className, and id. The dash_core_components library generates higher-level components like controls and graphs.

   The second part of the tutorial describes how to make your Dash apps interactive.

dash_input_output.py

#coding=utf-8
'''
@Author: zhangjian
@File: example.py
@Date:17-8-1 下午2:00
'''
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
# 实例化一个dash对象
app = dash.Dash()
# 布局结构:
# 1 整个页面由一个div构成
# 2 div里面有一个input输入框
# 3 input框后面有一个空的子div
app.layout = html.Div([
    dcc.Input(id='my-id', value='initial value', type="text"),
    html.Div(id='my-div')
])
# 回调函数
@app.callback(
    Output(component_id='my-div', component_property='children'),
    [Input(component_id='my-id', component_property='value')]
)
# 更新子div
def update_output_div(input_value):
    return '您当前的输入为:"{}"'.format(input_value)
if __name__ == '__main__':
    app.run_server()

运行结果如下:


这里写图片描述

注:输入框和子div显示的不一致的原因是update_output_div()方法的入参是input_value原始的键盘输入;

Notes

Try typing in the text box. The children of the output component updates right away. Let's break down what's happening here:

  1. The “inputs” and “outputs” of our application interface are described declaratively through the app.callback decorator.

  2. In Dash, the inputs and outputs of our application are simply the properties of a particular(独有的,特别的) component. In this example, our input is the “value” property of the component that has the ID “my-id”. Our output is the “children” property of the component with the ID “my-div”.

  3. Whenver an input property changes, the function that the callback decorator wraps will get called automatically. Dash provides the function with the new value of the input property as an input argument and Dash updates the property of the output component with whatever was returned by the function.

  4. The component_id and component_property keywords are optional (there are only two arguments for each of those objects). I have included them here for clarity but I will omit them from here on out for brevity and readability.

  5. Don’t confuse the dash.dependencies.Input object from the dash_core_components.Input object. The former is just used in these callbacks and the latter is an actual component.

  6. Notice how we don’t set a value for the children property of the my-div component in the layout. When the Dash app starts, it automatically calls all of the callbacks with the initial values of the input components in order to populate the initial state of the output components. In this example, if you specified something like html.Div(id=’my-div’, children=’Hello world’), it would get overwritten when the app starts.
    It’s sort of like programming with Microsoft Excel: whenever an input cell changes, all of the cells that depend on that cell will get updated automatically. This is called “Reactive Programming”.
    Remember how every component was described entirely through its set of keyword arguments? Those properties are important now. With Dash interactivity, we can dynamically update any of those properties through a callback function. Frequently we’ll update the children of a component to display new text or the figure of a dcc.Graph component to display new data, but we could also update the style of a component or even the available options of a dcc.Dropdown component!

dash_slider_dpdate_graph.py

(a dcc.Slider updates a dcc.Graph)

# coding=utf-8
'''
@Author: zhangjian
@File: dash_splider_update_graph.py
@Date:17-8-1 下午2:40
'''
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
# 读取csv文件
df = pd.read_csv(
    'https://raw.githubusercontent.com/plotly/'
    'datasets/master/gapminderDataFiveYear.csv')
# 创建dash实例
app = dash.Dash()
'''
布局:
1\. 整个页面由一个div构成
2\. div里面有一个dcc.Graph构建的图形
3\. 图形下面有一个滑动条
   滑动条的属性:
   - id:唯一标识,类似与html标签的id属性,用来唯一定位这个标签;
   - min:范围下限
   - max:范围上限
   - value:滑动条的当前值
   - step:
   - marks:滑动条上的刻度名称
'''
app.layout = html.Div([
    dcc.Graph(id='graph-with-slider', animate=True),
    dcc.Slider(
        id='year-slider',
        min=df['year'].min(),
        max=df['year'].max(),
        value=df['year'].min(),
        step=None,
        marks={str(year): str(year) for year in df['year'].unique()}
    )
])
# 回调函数的写法:@dash_object_name.callback(xxxxxxx)
@app.callback(
    # 图形作为输出的载体
    dash.dependencies.Output('graph-with-slider', 'figure'),
    # 滑动条作为输入的载体
    [dash.dependencies.Input('year-slider', 'value')])
# 针对滑动操作的回调函数,输入参数为滑动条的当前值
def update_figure(selected_year):
    # 从dataframe中过滤出特定年份的数据
    filtered_df = df[df.year == selected_year]
    # 空的列表,作为装载实时数据的容器
    traces = []
    # 遍历
    for i in filtered_df.continent.unique():
        # 每行
        df_by_continent = filtered_df[filtered_df['continent'] == i]
        # 从每行中抽取属性值,并添加到列表中
        traces.append(go.Scatter(
            x=df_by_continent['gdpPercap'],
            y=df_by_continent['lifeExp'],
            text=df_by_continent['country'],
            mode='markers',
            opacity=0.7,
            marker={
                'size': 15,
                'line': {'width': 0.5, 'color': 'white'}
            },
            name=i
        ))
    # 返回值
    # 数据和布局
    return {
        'data': traces,
        'layout': go.Layout(
            xaxis={'type': 'log', 'title': 'GDP Per Capita'},
            yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
            margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
            legend={'x': 0, 'y': 1},
            hovermode='closest'
        )
    }
if __name__ == '__main__':
    app.run_server()

运行结果如图:


这里写图片描述

Notes

In this example, the "value" property of the Slider is the input of the app and the output of the app is the "figure" property of the Graph. Whenever the value of the Slider changes, Dash calls the callback function update_figure with the new value. The function filters the dataframe with this new value, constructs a figure object, and returns it to the Dash application.

There are a few nice patterns in this example:

  1. We’re using the Pandas library for importing and filtering datasets in memory.

  2. We load our dataframe at the start of the app: df = pd.read_csv(‘…’). This dataframe df is in the global state of the app and can be read inside the callback functions.

  3. Loading data into memory can be expensive. By loading querying data at the start of the app instead of inside the callback functions, we ensure that this operation is only done when the app server starts. When a user visits the app or interacts with the app, that data (the df) is already in memory. If possible, expensive initialization (like downloading or querying data) should be done in the global scope of the app instead of within the callback functions.

  4. The callback does not modify the original data, it just creates copies of the dataframe by filtered through pandas filters. This is important: your callbacks should never mutate variables outside of their scope. If your callbacks modify global state, then one user’s session might affect the next user’s session and when the app is deployed on multiple processes or threads, those modifications will not be shared across sessions.

Multiple inputs

In Dash any "Output" can have multiple "Input" components. Here's a simple example that binds 5 Inputs (the value property of 2 Dropdown components, 2 RadioItems components, and 1 Slider component) to 1 Output component (the figure property of the Graph component). Notice how the app.callback lists all 5 dash.dependencies.Input inside a list in the second argument.

multiple inputs.py

#coding=utf-8
'''
@Author: zhangjian
@File: multipleInput.py
@Date:17-8-1 下午3:40
'''
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
# 实例化dash对象
app = dash.Dash()
# 读取csv文件
df = pd.read_csv(
    'https://gist.githubusercontent.com/chriddyp/'
    'cb5392c35661370d95f300086accea51/raw/'
    '8e0768211f6b747c0db42a9ce9a0937dafcbd8b2/'
    'indicators.csv')
# 获取dataFrame中Indicator Name这一列的所有值
available_indicators = df['Indicator Name'].unique()
'''
布局:
1\. 页面是由一个div构成的
2\. div里面有一个子div
3\. 子div里面有两个子div
4\. 最内层的两个div里面各有dropdown,radioItems两个组件
'''
app.layout = html.Div([
    html.Div([
        html.Div([
            # 输入
            dcc.Dropdown(
                # 唯一标识
                id='xaxis-column',
                # value为dataframe的INdicator Name列的所有值
                options=[{'label': i, 'value': i} for i in available_indicators],
                value='Fertility rate, total (births per woman)'
            ),
            # 输入
            dcc.RadioItems(
                id='xaxis-type',
                # value为Linear||Log
                options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
                value='Linear',
                labelStyle={'display': 'inline-block'}
            )
        ],
        style={'width': '48%', 'display': 'inline-block'}),
        html.Div([
            # 输入
            dcc.Dropdown(
                id='yaxis-column',
                options=[{'label': i, 'value': i} for i in available_indicators],
                value='Life expectancy at birth, total (years)'
            ),
            # 输入
            dcc.RadioItems(
                id='yaxis-type',
                options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
                value='Linear',
                labelStyle={'display': 'inline-block'}
            )
        ],style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
    ]),
    # 输出
    dcc.Graph(id='indicator-graphic'),
    # 输入
    dcc.Slider(
        id='year--slider',
        min=df['Year'].min(),
        max=df['Year'].max(),
        value=df['Year'].max(),
        step=None,
        marks={str(year): str(year) for year in df['Year'].unique()}
    )
])
'''
回调列表
多输入-单输出
输入:
两个单选框
两个下拉框
一个滑动条
输出:
graph
'''
@app.callback(
    dash.dependencies.Output('indicator-graphic', 'figure'),
    [dash.dependencies.Input('xaxis-column', 'value'),
     dash.dependencies.Input('yaxis-column', 'value'),
     dash.dependencies.Input('xaxis-type', 'value'),
     dash.dependencies.Input('yaxis-type', 'value'),
     dash.dependencies.Input('year--slider', 'value')])
'''
输入发生改变时(单选框,下拉框,滑动条)触发的回调函数
'''
def update_graph(xaxis_column_name, yaxis_column_name,
                 xaxis_type, yaxis_type,
                 year_value):
    dff = df[df['Year'] == year_value]
    return {
        'data': [go.Scatter(
            x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],
            y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],
            text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],
            mode='markers',
            marker={
                'size': 15,
                'opacity': 0.5,
                'line': {'width': 0.5, 'color': 'white'}
            }
        )],
        'layout': go.Layout(
            xaxis={
                'title': xaxis_column_name,
                'type': 'linear' if xaxis_type == 'Linear' else 'log'
            },
            yaxis={
                'title': yaxis_column_name,
                'type': 'linear' if yaxis_type == 'Linear' else 'log'
            },
            margin={'l': 40, 'b': 40, 't': 10, 'r': 0},
            hovermode='closest'
        )
    }
if __name__ == '__main__':
    app.run_server()

运行结果如图:


这里写图片描述

Notes

In this example, the update_graph function gets called whenever the value property of the Dropdown, Slider, or RadioItems components change.

The input arguments of the update_graph function are the new or current value of the each of the Input properties, in the order that they were specified.

Even though only a single Input changes at a time (a user can only change the value of a single Dropdown in a given moment), Dash collects the current state of all of the specified Input properties and passes them into your function for you. Your callback functions are always guarenteed to be passed the representative state of the app.

Multiple Outputs

Each Dash callback function can only update a single Output property. To update multiple Outputs, just write multiple functions.

multipleOutput.py

# coding=utf-8
'''
@Author: zhangjian
@File: multipleOutput.py
@Date:17-8-1 下午4:55
'''
import dash
import dash_core_components as dcc
import dash_html_components as html
# 实例化dash对象
app = dash.Dash('')
'''
布局:
1\. 整个页面由一个div构成
2\. div里面有一个radioItems1组件
3\. radioItems组件下面有个空的子div1
4\. div1下面有个radioItems2组件
5\. radioItems2组件下面有个空的子div2
'''
app.layout = html.Div([
    # 输入
    dcc.RadioItems(
        id='dropdown-a',
        options=[{'label': i, 'value': i} for i in ['Canada', 'USA', 'Mexico']],
        value='Canada'
    ),
    # 输出
    html.Div(id='output-a'),
    # 输入
    dcc.RadioItems(
        id='dropdown-b',
        options=[{'label': i, 'value': i} for i in ['MTL', 'NYC', 'SF']],
        value='MTL'
    ),
    # 输出
    html.Div(id='output-b')
])
'''
回调列表
'''
@app.callback(
    # 输出
    dash.dependencies.Output('output-a', 'children'),
    # 输入
    [dash.dependencies.Input('dropdown-a', 'value')])
# id为dropdown-a的radioItems的值发生change时触发的回调函数
def callback_a(dropdown_value):
    return 'You\'ve selected "{}"'.format(dropdown_value)
'''
回调列表
'''
@app.callback(
    # 输出
    dash.dependencies.Output('output-b', 'children'),
    # 输入
    [dash.dependencies.Input('dropdown-b', 'value')])
# id为dropdown-b的radioItems的值发生change时触发的回调函数
def callback_b(dropdown_value):
    return 'You\'ve selected "{}"'.format(dropdown_value)
if __name__ == '__main__':
    app.run_server()

运行结果如图:


这里写图片描述

Summary

We've covered the fundamentals of Dash. Dash apps are built off of a set of simple but powerful principles: declarative UIs that are customizable through reactive and functional Python callbacks. Every element attribute of the declarative components can be updated through a callback and a subset of the attributes, like the value properties of the dcc.Dropdown, are editable by the user in the interface.

</article>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容