【数据可视化】基于Dash制作的疫情数据可视化APP(Dash入门必读,附可运行源码)
基于Dash制作的疫情数据可视化APP
在此之前,我写过一篇博客《基于Streamlit制作的时间序列数据分析APP》。Streamlit的优点是上手简单、能在短时间内快速构建具有一定交互性的WebAPP,缺点也显而易见:样式较为固定、运行速度慢。
本篇博客,我将利用一种新的方式——Dash,来构建一个疫情数据可视化APP。Dash与Streamlit相比又有何优缺点呢?让我们一起来看看吧!
1.Dash介绍
官网介绍链接:https://dash.plotly.com/introduction
1.1 Dash简介(Introduction)
Dash是一个用于构建Web分析应用程序的高效Python框架。Dash应用程序由两部分组成:
- 应用程序的“布局”,它描述了应用程序的外观。
- 应用程序的交互性。
Dash基于Flask,Plotly.js和React.js,可高度自定义用户界面。如果你是纯Python用户,那么Dash一定是构建数据可视化应用程序的理想选择。
通过几个简单的模式,Dash提取了构建基于Web的交互式应用程序所需的所有技术和协议。Dash应用程序在Web浏览器中呈现。
我们可以将应用程序部署到服务器,然后通过URL共享它们。由于Dash应用程序是在Web浏览器中查看的,因此Dash本质上是跨平台且可移动的。
1.2 安装(Installation)
pip install dash
import dash
import dash_core_components as dcc
import dash_html_components as html
1.3 布局(Layout)
dash的布局由html.Div
和dcc.Graph
等“组件”共同构成。
dash_html_components
库对于每个HTML标签都有一个组件。比如,html.H1(children=‘Hello Dash’)
相当于<h1> Hello Dash </h1>
。
dash_core_components
则描述了更高级的交互式组件,这些组件是通过React.js库使用JavaScript、HTML和CSS生成的。
Dash是声明性的。每个组件都是通过关键字属性来描述。children属性比较特别,它始终是第一个属性,一般情况下我们可以忽略它。html.H1(children=‘Hello Dash’)
与html.H1(‘Hello Dash’)
相同。而且,它可以包含字符串,数字,单个组件或组件列表。
1.4 回调函数(Basic Callbacks)
回调函数:每当输入组件的属性发生更改时,Dash会自动调用的函数。
我们将应用程序接口的inputs
和outputs
声明为@app.callback
装饰器的参数。在Dash中,我们应用程序的输入和输出只是特定组件的属性。只要输入属性发生变化,回调函数就会自动调用。 Dash为函数提供输入属性的新值作为输入参数,Dash使用函数返回的值更新输出组件的属性。
Dash应用程序启动时,它将自动使用输入组件的初始值调用所有回调,以填充输出组件的初始状态。借助Dash的交互性,我们可以通过回调函数动态更新任何属性。比如,我们将更新组件的子模块以显示新文本,或者更新dcc.Graph
组件的图形以显示新数据。
1.5 交互可视化(Interactive Visualizations)
dash_core_components
库包含一个名为Graph的组件。Graph使用开源plotly.js
图形库呈现交互式数据可视化。dcc.Graph
组件中的图形参数与Plotly的图形库使用的图形参数相同。
我们通过一组属性声明性地描述dash组件。所有的这些属性都可以通过回调函数进行更新,但是这些属性的子集只能通过用户交互来更新。例如,当我们单击dcc.Dropdown
组件中的一个选项时,该组件的value属性将发生更改。
dcc.Graph
组件具有四个可以通过用户交互更改的属性:hoverData
,clickData
,selectedData
,relayoutData
。当我们将鼠标悬停在点上、单击点或选择图形中的点区域时,这些属性将会更新。
2.Dash实战:疫情数据可视化
下面将结合一个“疫情数据可视化”实例来熟悉dash及其各种组件。
本文所有代码均已上传至我的Github,需要的朋友可以自行下载。
最后的呈现效果如下图所示。
2.1 导入依赖包
import pandas as pd
pd.set_option('max_rows',20)
import plotly.express as px
import plotly.io as pio
pio.renderers.default = "browser"
dash_core_components
和dash_html_components
是Dash中非常重要的两个组件。
dash-bootstrap-components
是用于Plotly Dash的Bootstrap组件库。
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
external_stylesheets = [dbc.themes.BOOTSTRAP]app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.title = 'Covid-19 Dashboard'
2.2 获取数据
全球疫情数据是从20年1月22日至今(就是您看博客的这一天)。由于统计方法的不同,可能有部分数据不准确。
# 确诊数据
CONF_URL = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv'# 死亡数据
DEAD_URL = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_deaths_global.csv'# 治愈数据
RECV_URL = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv'
covid_conf_ts = pd.read_csv(CONF_URL)
covid_dead_ts = pd.read_csv(DEAD_URL)
covid_recv_ts = pd.read_csv(RECV_URL)
2.3 数据处理
# 以规整的时间序列格式获取某个国家或地区的疫情数据
def process_data(data,cntry='China',window=3):conf_ts = dataconf_ts_cntry = conf_ts[conf_ts['Country/Region']==cntry]final_dataset = conf_ts_cntry.T[4:].sum(axis='columns').diff().rolling(window=window).mean()[40:]df = pd.DataFrame(final_dataset,columns=['Total'])return df
# 获取全球确诊、治愈和死亡的总数据
def get_overall_total(df):return df.iloc[:,-1].sum()conf_overall_total = get_overall_total(covid_conf_ts)
dead_overall_total = get_overall_total(covid_dead_ts)
recv_overall_total = get_overall_total(covid_recv_ts)
# 获取某个国家或地区的确诊、治愈和死亡的总数据
def get_cntry_total(df,cntry='China'):return df[df['Country/Region']==cntry].iloc[:,-1].sum()cntry = 'China'
conf_cntry_total = get_cntry_total(covid_conf_ts,cntry)
dead_cntry_total = get_cntry_total(covid_dead_ts,cntry)
recv_cntry_total = get_cntry_total(covid_recv_ts,cntry)
2.4 利用Plotly绘图
# 绘制确诊病例数据折线图
def fig_world_trend(cntry='China',window=3):df = process_data(data=covid_conf_ts,cntry=cntry,window=window)df.head(10)if window==1:yaxis_title = "Daily Cases"else:yaxis_title = "Daily Cases ({}-day MA)".format(window)fig = px.line(df, y='Total', x=df.index, title='Daily confirmed cases trend for {}'.format(cntry),height=600,color_discrete_sequence =['maroon'])fig.update_layout(title_x=0.5,plot_bgcolor='#F2DFCE',paper_bgcolor='#F2DFCE',xaxis_title="Date",yaxis_title=yaxis_title)return fig
2.5 网页顶部标题设计
colors = {'background': '#111111','bodyColor':'#F2DFCE','text': '#7FDBFF'
}# 网页头部设计
def get_page_heading_style():return {'backgroundColor': colors['background']}# 网页标题设计
def get_page_heading_title():return html.H1(children='COVID-19 Dashboard',style={'textAlign': 'center','color': colors['text']})# 网页副标题设计
def get_page_heading_subtitle():return html.Div(children='Visualize Covid-19 data generated from sources all over the world.',style={'textAlign':'center','color':colors['text']})
利用dbc.Row
和dbc.Col
组合标题和副标题。
# 合并标题与副标题
def generate_page_header():main_header = dbc.Row([dbc.Col(get_page_heading_title(),md=12)],align="center",style=get_page_heading_style())subtitle_header = dbc.Row([dbc.Col(get_page_heading_subtitle(),md=12)],align="center",style=get_page_heading_style())header = (main_header,subtitle_header)return header
2.6 下拉选择框设计
# 获取所有国家或地区的名称列表
def get_country_list():return covid_conf_ts['Country/Region'].unique()# 生成一个排好序的国家或地区名称列表
def create_dropdown_list(cntry_list):dropdown_list = []for cntry in sorted(cntry_list):tmp_dict = {'label':cntry,'value':cntry}dropdown_list.append(tmp_dict)return dropdown_list
利用dcc.Dropdown
生成下拉列表。
def get_country_dropdown(id):return html.Div([html.Label('Select Country'),dcc.Dropdown(id='my-id'+str(id),options=create_dropdown_list(get_country_list()),value='China'),html.Div(id='my-div'+str(id))])
2.7 图形容器
将fig_world_trend()
生成的图形传入dcc.Graph
生成的图形容器中。
def graph1():return dcc.Graph(id='graph1',figure=fig_world_trend('China'))
2.8 卡片设计
我们将以卡片的形式呈现确诊、治愈、死亡数据。
def generate_card_content(card_header,card_value,overall_value):card_head_style = {'textAlign':'center','fontSize':'150%'}card_body_style = {'textAlign':'center','fontSize':'200%'}card_header = dbc.CardHeader(card_header,style=card_head_style)card_body = dbc.CardBody([html.H5(f"{int(card_value):,}", className="card-title",style=card_body_style),html.P("Worlwide: {:,}".format(overall_value),className="card-text",style={'textAlign':'center'}),])card = [card_header,card_body]return card
利用dbc.Card
生成卡片。利用dbc.Row
和dbc.Col
排列卡片。
def generate_cards(cntry='China'):conf_cntry_total = get_cntry_total(covid_conf_ts,cntry)dead_cntry_total = get_cntry_total(covid_dead_ts,cntry)recv_cntry_total = get_cntry_total(covid_recv_ts,cntry)cards = html.Div([dbc.Row([dbc.Col(dbc.Card(generate_card_content("Recovered",recv_cntry_total,recv_overall_total), color="success", inverse=True),md=dict(size=2,offset=3)),dbc.Col(dbc.Card(generate_card_content("Confirmed",conf_cntry_total,conf_overall_total), color="warning", inverse=True),md=dict(size=2)),dbc.Col(dbc.Card(generate_card_content("Dead",dead_cntry_total,dead_overall_total),color="dark", inverse=True),md=dict(size=2)),],className="mb-4",),],id='card1')return cards
2.9 滑动条设计
利用dcc.Slider
生成滑动条,用来选择移动平均窗口大小。
def get_slider():return html.Div([ dcc.Slider(id='my-slider',min=1,max=15,step=None,marks={1: '1',3: '3',5: '5',7: '1-Week',14: 'Fortnight'},value=3,),html.Div([html.Label('Select Moving Average Window')],id='my-div'+str(id),style={'textAlign':'center'})])
2.10 页面布局
将前面设计完成的所有组件进行页面布局。
def generate_layout():page_header = generate_page_header()layout = dbc.Container([page_header[0],page_header[1],html.Hr(),generate_cards(),html.Hr(),dbc.Row([dbc.Col(get_country_dropdown(id=1),md=dict(size=4,offset=4)) ]),dbc.Row([ dbc.Col(graph1(),md=dict(size=6,offset=3))],align="center",),dbc.Row([dbc.Col(get_slider(),md=dict(size=4,offset=4)) ]),],fluid=True,style={'backgroundColor': colors['bodyColor']})return layout
app.layout = generate_layout()
2.11 回调函数(★★★)
本实例中有两个输入:
- 下拉列表选择的国家或地区。
- 滑动条选择的移动平均窗口大小。
同时也有两个输出:
- 卡片上的数据将得到更新。
- 图形将会得到更新。
@app.callback([Output(component_id='graph1',component_property='figure'), #line chartOutput(component_id='card1',component_property='children')], #overall card numbers[Input(component_id='my-id1',component_property='value'), #dropdownInput(component_id='my-slider',component_property='value')] #slider
)
def update_output_div(input_value1,input_value2):return fig_world_trend(input_value1,input_value2),generate_cards(input_value1)
2.12 运行
if __name__ == '__main__':app.run_server(debug=True)
呈现效果如下所示:
3.总结
优点 | 缺点 | |
---|---|---|
Streamlit | 简单易上手,快速搭建APP | 样式固定,运行速度慢 |
Dash | 样式多变,组件丰富 | 稍复杂,需要一定的HTML、CSS基础知识 |
本文所有代码均已上传至我的Github,需要的朋友可以自行下载。
https://github.com/Beracle/06-COVID-19-DashBoard
【数据可视化】基于Dash制作的疫情数据可视化APP(Dash入门必读,附可运行源码)相关推荐
- java毕业设计基于BS架构的疫情包联信息管理系统的设计与实现mybatis+源码+调试部署+系统+数据库+lw
java毕业设计基于BS架构的疫情包联信息管理系统的设计与实现mybatis+源码+调试部署+系统+数据库+lw java毕业设计基于BS架构的疫情包联信息管理系统的设计与实现mybatis+源码+调 ...
- 埋点数据mysql分析_用户行为分析-埋点实时数仓实践(附用户关联源码)
一.概述 埋点采集.用户行为分析.实时数仓.IdMapping 此文重点讲述埋点的数据模型.数据格式.数据实时采集.加工.存储及用户关联.关于用户行为分析的概念.意义以及埋点相关的东西此文不作赘述 二 ...
- 【数据可视化】基于Streamlit制作的时间序列数据分析APP(上手简单,附可运行源码)
基于Streamlit制作的时间序列数据分析APP 1.为什么要使用Streamlit(官网介绍链接) 在数据科学领域,一方面,当我们在学习或者实践机器学习算法的时候,需要进行一些参数调整:另一方面, ...
- 基于springboot的高校疫情打卡上报系统设计与实现 文档+项目源码及数据库文件+演示视频
基于springboot的高校疫情打卡上报系统设计与实现 摘要:在互联网环境下结合疫情防控要求,开发了基于微信小程序的体温填报.信息预警管理平台.随着微信小程序的热度越来越高,更多的人将目光放在这个平 ...
- 基于SSM框架的疫情防控管理系统设计与实现.rar(论文+项目源码)
概述/引言 1 1.1研究背景 1 1.2国内外的研究现状 1 1.3课题的基本内容 2 2 系统分析与主要技术 4 2.1 JSP技术 4 2.2 MySQL数据库 5 2.3需求分析 5 2.4数 ...
- html毕业作品,基于HTML制作的闲置交易网站设计毕业论文+开题报告+Html静态网页源码...
摘要 近年来,互联网已日益成为收集提供信息的最佳渠道并逐步进入传统的流通领域,于是电子商务开始流行起来.本次设计的购物系统,用户可以进行查看商品.购买下单.查询进度.反馈评价等诸多特色性功能.针对确定 ...
- 毕业设计-基于Python爬虫的疫情数据可视化系统
基于Python爬虫的疫情数据可视化系统 采用ECharts+Flask+Requests架构: 源码加3105088663
- javaweb课程设计-基于SSM框架的疫情数据统计分析系统源码+数据库,可以进行疫情数据录入、疫情数据查询、图表展示
疫情数据统计分析系统 完整代码下载地址:基于SSM框架的疫情数据统计分析系统源码+数据库 介绍 疫情数据统计分析系统是一个基于SSM框架的网页端系统,项目中实现的功能如下:用户访问网站可以浏览全国疫情 ...
- 极光大数据:2017年10月主流共享单车app运营报告(附下载)
报告下载:添加199IT官方微信[i199it],回复关键词[2017年10月主流共享单车app运营报告] 共享单车行业经历了一轮爆发式增长后,出现了马太效应,第一梯队的ofo摩拜越战越勇,而落后者则 ...
最新文章
- 程序员,应该掌握的英语词汇
- webmin远程命令执行漏洞(cve-2019-15107)深入分析
- python模糊查询_python实现字符串模糊匹配
- linux ksh怎么查找僵尸进程,Unix 进程管理
- 朱峰谈概念设计(一):概念设计与插画的区别
- linux 复制栈数据结构,算法-数据结构-堆栈
- php spry文本域_《PHP和MySQL Web 开发》第8章 设计Web数据库
- 如何领导团队做好技术债管理?
- Xdebug部分配置选项说明
- 暴力枚举——火柴棒等式(洛谷 P1149)
- python怎么提交作业_python分析作业提交情况
- HashMap的实现原理、JDK1.7和JDK1.8的对比以及死锁问题
- 项目中一些零碎化总结的
- 数据库之SQL笛卡尔积
- 点击电脑版微信一直打不开解决方案
- centos7挂载ntfs文件系统_CentOS7挂载NTFS格式的硬盘
- 数据倾斜的原因及解决方案
- 【零基础学Python】爬虫篇 :第十一节--Python爬虫Urllib用法合集
- SAP那些事-职业篇-2-AI能不能替代SAP顾问
- Python实现计算MD5