【Dash搭建可视化网站】项目13:销售数据可视化大屏制作步骤详解
销售数据可视化大屏制作步骤详解
- 1 项目效果图
- 2 项目架构
- 3 文件介绍和功能完善
- 3.1 assets文件夹介绍
- 3.2 app.py和index.py文件完善
- 3.3 header.py文件完善
- 3.4 api.py文件和api.ipynb文件完善
- 3.4.1 需求数据获取
- 3.4.2 header.py文件中数据变更
- 3.5 middle.py文件完善
- 3.5.1 中间第一部分图形绘制
- 3.5.2 中间第二部分图形绘制
- 3.5.3 中间第三部分图形绘制
- 3.5.4 中间第四部分信息卡片制作
- 3.6 bottom.py文件完善
- 3.6.1 底部第一个部分表格制作
- 3.6.2 底部第二部分图形绘制
- 3.6.3 底部第三部分图形绘制
- 4 样式修改
- 4.1 整体样式修改
- 4.2 header.py文件样式修改
- 4.3 middle.py文件样式修改
- 4.4 bottom.py文件样式修改
手动反爬虫: 原博地址 https://blog.csdn.net/lys_828/article/details/128646202
知识梳理不易,请尊重劳动成果,文章仅发布在CSDN网站上,在其他网站看到该博文均属于未经作者授权的恶意爬取信息
1 项目效果图
整个项目的页面包含三部分,由上中下三栏构成。项目已上传至 个人Github仓库 。
2 项目架构
项目中各文件名称与对应功能见下表 。整个项目是由上中下三部分组成,头部信息较为简单,重点在于中部和下部的内容设置。
3 文件介绍和功能完善
3.1 assets文件夹介绍
assets文件夹中就是加载的样式和图片,样式这里可以使用之前已经下载好的bootstrap.min.css样式(也可以按照 项目6.2bootstrap组件 中的介绍下载其它的样式模板),本次项目中不需要加载本地图片。
3.2 app.py和index.py文件完善
主框架就是app.py项目初始化文件和index.py主程序运行文件,其中app.py文件中的信息较为简单,就是创建一个dash的应用,代码如下。
index.py文件中引入初始化后的应用,然后进行布局及运行初始化设置。布局的主体是上中下三个部分,分别对应header.py、middle.py和bottom.py文件中的三个函数,具体代码如下。
from dash import html
import dash_bootstrap_components as dbc
from app import appfrom header import HeaderInfo
from middle import MiddleInfo
from bottom import BottomInfoapp.layout = html.Div([html.Div([HeaderInfo()]),html.Div([MiddleInfo()]),html.Div([BottomInfo()])]
)if __name__ == '__main__':app.run_server(debug=True)
布局的三个文件中的内容初始化如下,头部信息和底部信息都是一行三列,中间是一行四列布局。(api.py和api.ipynb文件暂时没有内容)
3.3 header.py文件完善
该文件包含了三个部分,最左侧是项目标题,对应一行文字;中间是一个时间选择Slider组件(Rangeslider组件是选取时间跨度,Slider组件是获取具体年份),右侧是一个RadioItems组件(Checklist组件是多选,Radioiitems组件是单选)。该文件中的全部代码如下。
from dash import html,dcc
import dash_bootstrap_components as dbcdef HeaderInfo():return dbc.Row([dbc.Col([html.H3('Sales Dashboard')]),dbc.Col([html.H6('销售年份'),dcc.Slider(min=2015,max=2018,step=1,value=2018,id='slider')]),dbc.Col([html.H6('Segment'),dcc.RadioItems(options=['Consumer','Comporate','Home Office'],value='Comporate',id='radio')]),])
保存文件后,运行index.py文件,点击网址http://127.0.0.1:8050/,刷新页面,输出结果如下。
3.4 api.py文件和api.ipynb文件完善
这两个文件会处理后续所有图表中需要使用到的数据,所以文件会根据需要进行代码加入。首先获取中间部分的数据,第一个图是不同子类别,不同地区下的年份销售数据;第二个图形是不同类别的年份销售数据占比;第三个图是不同月份的年份销售趋势图;第四个是年份销售额相关数据。
3.4.1 需求数据获取
打开api.ipynb文件,读入数据文件。
然后借助时间解析函数,快速获取年、月、日信息。
接着获取年份和部门的唯一值,这里是用作头部信息中的数据,替换掉当时指定的固定数值。
最后就是封装一个get_data()
函数,里面有两个参数year
和segment
,就是对应着头部信息中的两个筛选组件的标签,方便回调时快速获取数据。
把以上的代码转移到api.py文件中,此时api.py中的全部代码如下。
import pandas as pd
import warnings #由于版本的关系可能出现警告,忽略掉即可
warnings.filterwarnings('ignore')#读入数据文件
data = pd.read_csv('data/train.csv')def get_year_month_day(df,time_col):'''Extract the year, month, and day of the time field data'''df[time_col] = pd.to_datetime(df[time_col])df['year'] = df[time_col].dt.yeardf['month'] = df[time_col].dt.monthdf['day'] = df[time_col].dt.dayreturn df#借助时间解析函数,获取年、月、日信息
data = get_year_month_day(data,'Order Date')#获取数据的年份唯一值,核实没有缺失值None
year_ls = data['year'].unique()# 获取类别部门唯一值,核实没有缺失值
segment_ls = data['Segment'].unique()#封装获取数据的过程,方便回调
def get_data(year,segment):return data[(data['year']==year) & (data['Segment']==segment)]
3.4.2 header.py文件中数据变更
然后把数据变量导入到文件中使用,首先把头部信息中的Slider组件和RadioItems组件标签更换一下,如下。
3.5 middle.py文件完善
3.5.1 中间第一部分图形绘制
接着处理中间部分第一个的图像。首先解决数据问题,该图中上方还有一个筛选的组件,然后图中显示的信息就是按照这个组件的标签显示。即使用get_data()
函数获取数据后,再按照上方的指定标签进行Sales
字段的分组求和,最后进行排序后输出前五条数据。
此时该文件中的全部代码如下。
from dash import html,dcc,Input,Output
import dash_bootstrap_components as dbc
from app import app
from api import get_data
import plotly.express as pxdef MiddleInfo():return dbc.Row([dbc.Col([Sub_Category_or_Region()]),dbc.Col([]),dbc.Col([]),dbc.Col([])])def Sub_Category_or_Region():return html.Div([dcc.RadioItems(['Sub-Category','Region'],'Sub-Category',id = 'radio-sub-category-or-region'),dcc.Graph(id='h-bar-sub-category-or-region')])@app.callback(Output('h-bar-sub-category-or-region','figure'),[Input('slider-year','value'),Input('radio-segment','value'),Input('radio-sub-category-or-region','value')]
)
def update(year,segment,sub_category_or_region):df = get_data(year,segment)sales_data_series = df.groupby(sub_category_or_region)['Sales'].sum().sort_values(ascending=False)[:5][::-1]fig = px.bar(x=sales_data_series.values,y=sales_data_series.index,orientation='h')fig.update_layout(margin=dict(t=50,r=0,l=0,b=0),title={'text': f'Sales by {sub_category_or_region} {year}','y': 0.99,'x': 0.5,'xanchor': 'center','yanchor': 'top'})return fig
保存文件后,刷新网页,输出结果如下。测试图中的信息可以随着筛选组件的选择发生变化(包括头部的筛选组件)
3.5.2 中间第二部分图形绘制
该图形是按照类别Category字段统计年份销售额的占比情况。定义一个CategoryPie()
函数用于创建容器只需要指定一个id即可,然后放在布局的第二个Col()
中,此部分的代码如下。
def CategoryPie():return dcc.Graph(id='pie-category')@app.callback(Output('pie-category','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)type_ = 'Category'sales_data_series = df.groupby(type_)['Sales'].sum()fig=px.pie(values=sales_data_series.values,names=sales_data_series.index)fig.update_layout(margin=dict(t=50,r=0,l=0,b=0),title={'text': f'Sales by {type_} {year}','y': 0.99,'x': 0.5,'xanchor': 'center','yanchor': 'top'})return fig
保存文件后,刷新网址,输出内容如下。
通过观察,发现图形布局样式的更新存在大量的代码重复,因此,可以考虑封装一个函数,把样式布局当做一个共用的,减少重复代码。
##以下是共用的部分
def update_layout(fig,type_,year):fig.update_layout(margin=dict(t=50,r=0,l=0,b=0),title={'text': f'Sales by {type_} {year}','y': 0.99,'x': 0.5,'xanchor': 'center','yanchor': 'top'})return fig
此时该文件中的代码简化如下。这样做的好处在于该项目中5个图都用到了这个样式更新,因此可以直接封装一个简单的函数,后续根据需要修改完善参数,进行更详细的布局样式的更改,这样会简化很多的重复代码,看上去十分清爽。
from dash import html,dcc,Input,Output
import dash_bootstrap_components as dbc
from app import app
from api import get_data
import plotly.express as pxdef MiddleInfo():return dbc.Row([dbc.Col([Sub_Category_or_Region()]),dbc.Col([CategoryPie()]),dbc.Col([]),dbc.Col([])])##以下是共用的部分
def update_layout(fig,type_,year):fig.update_layout(margin=dict(t=50,r=0,l=0,b=0),title={'text': f'Sales by {type_} {year}','y': 0.99,'x': 0.5,'xanchor': 'center','yanchor': 'top'})return fig##以下是第一个图形中的内容设置
def Sub_Category_or_Region():return html.Div([dcc.RadioItems(['Sub-Category','Region'],'Sub-Category',id = 'radio-sub-category-or-region'),dcc.Graph(id='h-bar-sub-category-or-region')])@app.callback(Output('h-bar-sub-category-or-region','figure'),[Input('slider-year','value'),Input('radio-segment','value'),Input('radio-sub-category-or-region','value')]
)
def update(year,segment,sub_category_or_region):df = get_data(year,segment)sales_data_series = df.groupby(sub_category_or_region)['Sales'].sum().sort_values(ascending=False)[:5][::-1]fig = px.bar(x=sales_data_series.values,y=sales_data_series.index,orientation='h')return update_layout(fig,sub_category_or_region,year)##以下是第二个图形内容设置
def CategoryPie():return dcc.Graph(id='pie-category')@app.callback(Output('pie-category','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)type_ = 'Category'sales_data_series = df.groupby(type_)['Sales'].sum()fig=px.pie(values=sales_data_series.values,names=sales_data_series.index)return update_layout(fig,type_,year)
3.5.3 中间第三部分图形绘制
该图形是按月份进行年份销售数据的统计。首先需要筛选年份的个月销售额,即按照月份进行分组合并求和即可。定义一个MonthLine()
函数用于创建容器只需要指定一个id即可,然后放在布局的第三个Col()
中,此部分的代码如下。
##以下是第三个图形的内容设置
def MonthLine():return dcc.Graph(id='line-month')@app.callback(Output('line-month','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)type_='month'sales_data_series = df.groupby(type_)['Sales'].sum()print(sales_data_series)fig = px.line(x=sales_data_series.index,y=sales_data_series.values)return update_layout(fig,type_,year)
保存文件后,刷新网址,输出内容如下。
3.5.4 中间第四部分信息卡片制作
该部分是按照年份统计年份的销售额和相对于去年的增降幅,只和头部的年份筛选有关。定义一个YOY()
函数用于创建容器只需要指定一个id即可,然后放在布局的第四个Col()
中,此部分的代码如下。
##以下是第四部分的内容设置
def YOY():return html.Div(id='YOY')@app.callback(Output('YOY','children'),[Input('slider-year','value')]
)
def update(year):current_year_sales=data[data['year']==year]['Sales'].sum()if year != min(year_ls):previous_year_sales=data[data['year']==year-1]['Sales'].sum()yoy_growth=(current_year_sales-previous_year_sales)*100/previous_year_saleselse:previous_year_sales='No data'yoy_growth='No data'return [html.H6('Current Year'),html.P(f'${current_year_sales:,.0f}'),html.H6('Previous Year'),html.P(f'${previous_year_sales:,.0f}'),html.H6('YOY Grouth'),html.P(f'{yoy_growth:.2f}%'),]
保存文件后,刷新网址,输出内容如下。
此时middle.py文件中的内容初步设置完毕,文件中的全部代码如下。
from dash import html,dcc,Input,Output
import dash_bootstrap_components as dbc
from app import app
from api import get_data,year_ls,data
import plotly.express as pxdef MiddleInfo():return dbc.Row([dbc.Col([Sub_Category_or_Region()]),dbc.Col([CategoryPie()]),dbc.Col([MonthLine()]),dbc.Col([YOY()])])##以下是共用的部分
def update_layout(fig,type_,year):fig.update_layout(margin=dict(t=50,r=0,l=0,b=0),title={'text': f'Sales by {type_} {year}','y': 0.99,'x': 0.5,'xanchor': 'center','yanchor': 'top'})return fig##以下是第一个图形中的内容设置
def Sub_Category_or_Region():return html.Div([dcc.RadioItems(['Sub-Category','Region'],'Sub-Category',id = 'radio-sub-category-or-region'),dcc.Graph(id='h-bar-sub-category-or-region')])@app.callback(Output('h-bar-sub-category-or-region','figure'),[Input('slider-year','value'),Input('radio-segment','value'),Input('radio-sub-category-or-region','value')]
)
def update(year,segment,sub_category_or_region):df = get_data(year,segment)sales_data_series = df.groupby(sub_category_or_region)['Sales'].sum().sort_values(ascending=False)[:5][::-1]fig = px.bar(x=sales_data_series.values,y=sales_data_series.index,orientation='h')return update_layout(fig,sub_category_or_region,year)##以下是第二个图形内容设置
def CategoryPie():return dcc.Graph(id='pie-category')@app.callback(Output('pie-category','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)type_ = 'Category'sales_data_series = df.groupby(type_)['Sales'].sum()fig=px.pie(values=sales_data_series.values,names=sales_data_series.index)return update_layout(fig,type_,year)##以下是第三个图形的内容设置
def MonthLine():return dcc.Graph(id='line-month')@app.callback(Output('line-month','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)type_='month'sales_data_series = df.groupby(type_)['Sales'].sum()print(sales_data_series)fig = px.line(x=sales_data_series.index,y=sales_data_series.values)return update_layout(fig,type_,year)##以下是第四部分的内容设置
def YOY():return html.Div(id='YOY')@app.callback(Output('YOY','children'),[Input('slider-year','value')]
)
def update(year):current_year_sales=data[data['year']==year]['Sales'].sum()if year != min(year_ls):previous_year_sales=data[data['year']==year-1]['Sales'].sum()yoy_growth=(current_year_sales-previous_year_sales)*100/previous_year_saleselse:previous_year_sales='No data'yoy_growth='No data'return [html.H6('Current Year'),html.P(f'${current_year_sales:,.0f}'),html.H6('Previous Year'),html.P(f'${previous_year_sales:,.0f}'),html.H6('YOY Grouth'),html.P(f'{yoy_growth:.2f}%'),]
3.6 bottom.py文件完善
3.6.1 底部第一个部分表格制作
该部分是按照头部筛选条件获取的数据,最终以表格的形式展现出来。定义一个SaleTable()
函数用于创建容器只需要指定一个id即可,然后放在布局的第一个Col()
中,此部分的代码如下。
#以下是第一部分的内容设置
def SaleTable():return dash_table.DataTable(id='table-sale',page_size=15)@app.callback(Output('table-sale','data'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)filter_df = df[['Order Date', 'Customer ID', 'Customer Name','Segment', 'City', 'State', 'Region','Category', 'Sub-Category', 'Product Name','Sales', 'year', 'month']]return filter_df.to_dict('records')
保存文件后,刷新网址,输出内容如下。
3.6.2 底部第二部分图形绘制
该部分是按照州State还是城市City进行年销售数据的统计,此部分和中间第一部分图形的绘制类似,代码可以直接复制粘贴过来后小改一下。定义一个State_or_City()
函数用于创建容器,里面第一需要是构建一个RadioItems组件,再创建一个放置图形的容器设置id,然后放在布局的第二个Col()
中,此部分的代码如下。
from middle import update_layout
#以下是第二部分的内容设置
def State_or_City():return html.Div([dcc.RadioItems(['State','City'],'State',id='radio-state-or-city'),dcc.Graph(id='bar-state-or-city')])
@app.callback(Output('bar-state-or-city','figure'),[Input('slider-year','value'),Input('radio-segment','value'),Input('radio-state-or-city','value')]
)
def update(year,segment,state_or_city):df = get_data(year,segment)sales_data_series = df.groupby(state_or_city)['Sales'].sum().sort_values(ascending=False)[:5][::-1]fig = px.bar(x=sales_data_series.values,y=sales_data_series.index,orientation='h')return update_layout(fig,state_or_city,year)
保存文件后,刷新网址,输出内容如下。(直接把中间第一部分的代码复制过来,只修改几个名称就可复用)
此时下方的表格直接横跨了整个页面,后续再进行样式调整,目前只是功能实现。
3.6.3 底部第三部分图形绘制
该部分是按照月份进行州和城市年份销售数据的统计,最终结果以散点图的形式呈现。定义一个SaleTable()
函数用于创建容器只需要指定一个id即可,然后放在布局的第三个Col()
中,此部分的代码如下。此部分的State and City不是指两者字段相加,而是点击图形中的三点会同时显示当前月份下的State和City对应销售数据,需要使用到hover相关的参数。
#以下是第三部分的内容设置
def State_and_City():return dcc.Graph(id='scatter-state-and-city')@app.callback(Output('scatter-state-and-city','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment) obtain_fields = ['year', 'month', 'Segment', 'State', 'City']sales_data_df = df.groupby(obtain_fields)['Sales'].sum().reset_index()fig = px.scatter(sales_data_df,x=sales_data_df['month'],y=sales_data_df['Sales'],hover_data=obtain_fields)return update_layout(fig,'State and City',year)
保存文件后,刷新网址,输出内容如下。使用hover_data
需要前面先传入sales_data_df
(也就是与其对应的df)。
至此整个项目的全部功能都基本上完成,后续就是针对样式进行修改。
4 样式修改
4.1 整体样式修改
在assets文件夹下新建一个setting.css文件,设置整体风格。主要是背景、边缘和字体颜色的设置。
此时保存文件,刷新网页输出内容如下。由于表格中的字体设置成为白色后,和绘制图形的背景一致,所以导致看不见文字。
4.2 header.py文件样式修改
文字已经居中了,就只需要调整一下头部信息与中间信息和浏览器顶部的间距即可,修改样式内容如下。
此时保存文件,刷新网页输出内容如下。间距已经调整适合。
4.3 middle.py文件样式修改
首先需要设置card_container属性,把之前的代码直接复制过来,添加到对应组件中。属性中的背景颜色的设置课根据项目主题颜色进行修改,上一个项目是暗色调,这个项目是蓝色调。
此时保存文件,刷新网页输出内容如下。
然后针对于各个图形进行单独的样式设置,全部的代码如下。
from dash import html,dcc,Input,Output
import dash_bootstrap_components as dbc
from app import app
from api import get_data,year_ls,data
import plotly.express as px
import plotly.graph_objects as godef MiddleInfo():return dbc.Row([dbc.Col([Sub_Category_or_Region()],className='card_container',width=3),dbc.Col([CategoryPie()],className='card_container',width=3),dbc.Col([MonthLine()],className='card_container',width=4),dbc.Col([YOY()],className='card_container')])##以下是共用的部分
def update_layout(fig,type_,year):fig.update_layout(paper_bgcolor='#1f2c56',plot_bgcolor='#1f2c56',titlefont={'color': 'white','size': 15},font=dict(family='sans-serif',color='white',size=15),legend={'orientation': 'h','bgcolor': '#010915','xanchor': 'center', 'x': 0.5, 'y': -0.2},margin=dict(t=50,r=20,l=0,b=0),title={'text': f'Sales by {type_} {year}','y': 0.99,'x': 0.5,'xanchor': 'center','yanchor': 'top'},xaxis=dict(title='<b></b>',color = 'orange',showline=True,showgrid=False,showticklabels=True,linecolor='orange',linewidth=1,zeroline=False,ticks='outside',tickfont=dict(family='Aerial',color='orange',size=12)),yaxis=dict(title='<b></b>',color='orange',autorange = 'reversed',showline=True,showgrid=False,showticklabels=True,linecolor='orange',linewidth=1,zeroline=False,gridcolor='gray',ticks='outside',tickfont=dict(family='Aerial',color='orange',size=12)))return fig##以下是第一个图形中的内容设置
def Sub_Category_or_Region():return html.Div([dcc.RadioItems(['Sub-Category','Region'],'Sub-Category',id = 'radio-sub-category-or-region'),dcc.Graph(id='h-bar-sub-category-or-region')])@app.callback(Output('h-bar-sub-category-or-region','figure'),[Input('slider-year','value'),Input('radio-segment','value'),Input('radio-sub-category-or-region','value')]
)
def update(year,segment,sub_category_or_region):df = get_data(year,segment)sales_data_series = df.groupby(sub_category_or_region)['Sales'].sum().sort_values(ascending=False)[:5][::-1]fig = px.bar(x=sales_data_series.values,y=sales_data_series.index,orientation='h',text=sales_data_series)fig.update_layout(height=400)fig.update_traces(texttemplate='$' + '%{text:,.2s}', textposition='inside')return update_layout(fig,sub_category_or_region,year)##以下是第二个图形内容设置
def CategoryPie():return dcc.Graph(id='pie-category')@app.callback(Output('pie-category','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)type_ = 'Category'sales_data_series = df.groupby(type_)['Sales'].sum()fig=px.pie(values=sales_data_series.values,names=sales_data_series.index,hole=.7)# fig.update_layout(height=400)return update_layout(fig,type_,year)##以下是第三个图形的内容设置
def MonthLine():return dcc.Graph(id='line-month')@app.callback(Output('line-month','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)type_='month'sales_data_series = df.groupby(type_)['Sales'].sum()fig = go.Figure(go.Scatter(x=sales_data_series.index,y=sales_data_series.values,text = sales_data_series.values,texttemplate= '$' + '%{text:,.2s}',textposition='bottom left',mode='markers+lines+text',line=dict(width=3, color='orange'),marker=dict(color='#19AAE1', size=10, symbol='circle',line=dict(color='#19AAE1', width=2))))return update_layout(fig,type_,year)##以下是第四部分的内容设置
def YOY():return html.Div(id='YOY')@app.callback(Output('YOY','children'),[Input('slider-year','value')]
)
def update(year):current_year_sales=data[data['year']==year]['Sales'].sum()if year != min(year_ls):previous_year_sales=data[data['year']==year-1]['Sales'].sum()yoy_growth=(current_year_sales-previous_year_sales)*100/previous_year_saleselse:previous_year_sales='No data'yoy_growth='No data'return [html.H6('Current Year'),html.P(f'${current_year_sales:,.0f}',className='year_sale'),html.H6('Previous Year'),html.P(f'${previous_year_sales:,.0f}',className='year_sale'),html.H6('YOY Grouth'),html.P(f'{yoy_growth:.2f}%',className='year_sale'),]
保存文件,刷新网页输出内容如下。
4.4 bottom.py文件样式修改
该部分主要难点在于调整表格的大小问题,还有表格中的标题筛选。表格正常填充在卡片容器中需要指定参数virtualization=True
。然后再配合style_cell
和style_header
参数进行单元格和标题样式的设置。借助fixed_rows={'headers': True}
设置冻结首行,然后设置排序,并且允许多字段排序。
#以下是第一部分的内容设置
def SaleTable():return dash_table.DataTable(id='table-sale',page_size=15,virtualization=True,style_cell={'textAlign': 'left','min-width': '100px','backgroundColor': '#1f2c56','color': '#FEFEFE','border-bottom': '0.01rem solid #19AAE1'},style_header={'backgroundColor': '#1f2c56','fontWeight': 'bold','font': 'Lato, sans-serif','color': 'orange','border': '#1f2c56'},fixed_rows={'headers': True},sort_action='native',sort_mode='multi')@app.callback(Output('table-sale','data'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment)filter_df = df[['Order Date', 'Customer ID', 'Customer Name','Segment', 'City', 'State', 'Region','Category', 'Sub-Category', 'Product Name','Sales', 'year', 'month']]return filter_df.to_dict('records')
保存文件,刷新网页输出内容如下。
顺带也可以把表格的下部和右部的下拉组件设置一下样式。setting.css文件中修改样式如下。
/* width */
::-webkit-scrollbar {width: 10px !important;display: block !important;}/* Track */
::-webkit-scrollbar-track {background: #222b4a !important;border-radius: 10px !important;display: block !important;}/* Handle */
::-webkit-scrollbar-thumb {background:#1a2034 !important;
}/* Handle on hover */
::-webkit-scrollbar-thumb:hover {background: #1a2034 !important;
}.previous-next-container *{background: #1f2c56 !important;color: white !important;
}.current-page{background: #4c5575 !important;color: white !important;
}
保存文件,刷新网页输出内容如下。
最后两个图形的修改。其中底部第二部分的内容其实已经随着中间第一部分内容样式修改而发生变化了,只需要添加一个文字标注就可以了,然后最后一个图发现这折线图的y轴大小顺序翻过来了,需要调整一下(把之前middle.py文件中设置的autorange = 'reversed'
设置删除即可),最后设置一下散点的大小和颜色,两部分的代码修改如下。和前面的折线图设置类似,发现直接使用px下的绘制函数,没有办法详细地设置参数,因此又改变方式使用原生的go方式绘制图形。
#以下是第二部分的内容设置
def State_or_City():return html.Div([dcc.RadioItems(['State','City'],'State',id='radio-state-or-city'),dcc.Graph(id='bar-state-or-city')])
@app.callback(Output('bar-state-or-city','figure'),[Input('slider-year','value'),Input('radio-segment','value'),Input('radio-state-or-city','value')]
)
def update(year,segment,state_or_city):df = get_data(year,segment)sales_data_series = df.groupby(state_or_city)['Sales'].sum().sort_values(ascending=False)[:5][::-1]fig = px.bar(x=sales_data_series.values,y=sales_data_series.index,orientation='h',text=sales_data_series.values)fig.update_traces(texttemplate='$' + '%{text:,.2s}', textposition='inside')fig.update_layout(height=520)return update_layout(fig,state_or_city,year)#以下是第三部分的内容设置
def State_and_City():return dcc.Graph(id='scatter-state-and-city')@app.callback(Output('scatter-state-and-city','figure'),[Input('slider-year','value'),Input('radio-segment','value')]
)
def update(year,segment):df = get_data(year,segment) obtain_fields = ['year', 'month', 'Segment', 'State', 'City']sales_data_df = df.groupby(obtain_fields)['Sales'].sum().reset_index()fig = go.Figure(go.Scatter(x=sales_data_df['month'],y=sales_data_df['Sales'],mode='markers',line=dict(width=3, color='orange'),marker=dict(color= sales_data_df['Sales'],colorscale = 'HSV',showscale = False,size=sales_data_df['Sales'] / 250,symbol='circle',line=dict(color='MediumPurple', width=2)),hoverinfo='text',hovertext='<b>Year</b>: ' + sales_data_df['year'].astype(str) + '<br>' +'<b>Month</b>: ' + sales_data_df['month'].astype(str) + '<br>' +'<b>Segment</b>: ' + sales_data_df['Segment'].astype(str) + '<br>' +'<b>State</b>: ' + sales_data_df['State'].astype(str) + '<br>' +'<b>City</b>: ' + sales_data_df['City'].astype(str) + '<br>' +'<b>Sales</b>: $' + [f'{x:,.0f}' for x in sales_data_df['Sales']] + '<br>'))fig.update_layout(height=550)return update_layout(fig,'State and City',year)
保存文件,刷新网页输出内容如下。
至此,项目完结,撒花✿✿ヽ(°▽°)ノ✿。
【Dash搭建可视化网站】项目13:销售数据可视化大屏制作步骤详解相关推荐
- 【Dash搭建可视化网站】项目12:全球恐怖主义数据大屏制作步骤详解
全球恐怖主义数据大屏制作步骤详解 1 项目效果图 2 项目架构 3 文件介绍和功能完善 3.1 assets文件夹介绍 3.2 app.py和index.py文件完善 3.3 header.py文件完 ...
- 【Dash搭建可视化网站】项目10:疫情数据可视化大屏制作步骤详解
疫情数据可视化大屏制作步骤详解 1 项目效果图 2 项目架构 3 文件介绍和功能完善 3.1 assets文件夹介绍 3.2 app.py和index.py文件完善 3.3 header.py文件完善 ...
- python接口自动化(四十二)- 项目架构设计之大结局(超详解)
简介 这一篇主要是将前边的所有知识做一个整合,把各种各样的砖块-模块(post请求,get请求,logging,参数关联,接口封装等等)垒起来,搭建一个房子.并且有很多小伙伴对于接口项目测试的框架一筹 ...
- 熬了半宿做的表格PPT还是不能让老板客户满意?快来看看这些可视化大屏制作软件吧
在这个谁掌握的数据多谁就是强者的时代,如何快速理解数据想要表达的信息是我们提升生活质量和提高工作效率的一大杀手锏.以往我们使用的最多的数据展示软件多是Excel或PPT,但Excel只能整理数据,PP ...
- 2017云栖大会·杭州峰会:《在线用户行为分析:基于流式计算的数据处理及应用》之《数据可视化:构建实时动态运营数据分析大屏》篇...
实验背景介绍 了解更多2017云栖大会·杭州峰会 TechInsight & Workshop. 本手册为云栖大会Workshop之<在线用户行为分析:基于流式计算的数据处理及应用> ...
- 数据可视化大屏设计步骤,有3步流程
数据可视化大屏设计步骤,有3步流程 大屏工程师经常碰到那样的窘境:竭力设计方案的大屏,数据精确.視覺酷炫,可是用户满意度一般.究竟哪些的大屏才算是客户必须的呢?回答是:重点突出.层级清楚.怎样设计那样 ...
- 2017云栖大会·杭州峰会:《在线用户行为分析:基于流式计算的数据处理及应用》之《数据可视化:构建实时动态运营数据分析大屏》篇
点击有惊喜 实验背景介绍 了解更多2017云栖大会·杭州峰会 TechInsight & Workshop. 本手册为云栖大会Workshop之<在线用户行为分析:基于流式计算的数据处理 ...
- 从零开发可视化大屏制作平台
几个月前开源的H5页面制作平台H5-Dooring 收到了很多热心的反馈和交流, 顺着笔者之前的规划, 我们又做了一款可视化大屏编辑器V6.Dooring. 接下来笔者就来带大家一起看看我们的方案设计 ...
- 简单三步 一看就会的数据可视化大屏制作过程
今天为大家带来销售行业销售数据可视化的模板制作教程,对销售行业来说数据的展示是相当重要的,不仅因为销售数据展示的及时对销售行业能带来多少好处,同时也是为了减轻销售工作人员的压力,不用每次做数据统计时焦 ...
最新文章
- Java并发——ReentrantLock
- 用命令行为MySQL设置/修改管理员密码
- 老男孩教育每日一题-第108天-php-fpm优化关闭危险参数有哪些?
- Windows下安装ab
- 容器编排技术 -- Pod 安全策略
- java 的记住用户名和密码,JAVA--高级基础开发Cookie实现记住用户名和密码
- Win10电脑系统文件损坏怎么修复
- Security+ 学习笔记4 社会工程攻击
- R for data science之purrr包(上)
- Windows客户端使用教程
- 计算机如何通过手机连接网络,主编教您手机怎么通过usb连接电脑上网
- Java 旋转、翻转图片工具类(附代码) | Java工具类
- 个人微信淘客机器人api开发
- 2022 智简魔方财务快云模板前台+购物车+用户中心模板 全解 无授权
- tshark 使用说明
- 世界主要货币英文缩写
- 建武28a对讲机最大距离_TH-28A对讲机使用方法说明
- GprMax2D ——英国建筑研究机构(BRE)示例 #2
- 最大公因数及其求解算法(GCD)
- 赴德国旅游办理签证指南(转载)
热门文章
- 没有配置java环境变量,为什么我java环境变量都还没有配置都可以运行java程序了...
- javapoet动态生成java代码
- C/C++非专家级编程
- html5图片锐化,让照片达到最佳“锐度” 这5种“锐化”方式需掌握
- 抵抗不了“刷礼物”的诱惑,下架的斗鱼要上市有点难
- 51nod 1113 矩阵快速幂 模板
- IC笔试:​2022小米数字芯片提前批笔试
- gets与puts的使用,Str系列字符串的使用
- (九) 基于cadence 617 电流镜仿真对比 笔记记录
- linux-python升级到最新版本