【Dash搭建可视化网站】项目11:世界自杀率数据看板

手动反爬虫:原博地址 https://blog.csdn.net/lys_828/article/details/128624945

 知识梳理不易,请尊重劳动成果,文章仅发布在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文件中引入初始化后的应用,然后进行布局及运行初始化设置。布局的主体是上下两个部分,上面是项目的头部信息,下方是分为一行两列。

头部只有一个信息,使用HeaderInfo()填充内容,该函数分配在header.py文件中;而下部中左侧是有三个筛选组件,分别用三个函数填充,此三个函数分配在layoutleft.py文件中;右侧只有一个图形展示,使用Scatterchart()填充内容,该函数分配在layoutright.py文件中,该文件的全部代码如下。

from dash import html
from app import app
import dash_bootstrap_components as dbc

from header import HeaderInfo
from layoutleft import DropdownInfo,RangeSliderInfo,ChecklistInfo
from layoutright import Scatterchart

app.layout = html.Div(
    [
        html.Div([HeaderInfo()]),
        html.Div([
                dbc.Row(
                [
                    dbc.Col([DropdownInfo(),RangeSliderInfo(),ChecklistInfo()],width=4),
                    dbc.Col([Scatterchart()])
                ]
            )
        ])
    ]
)

if __name__ == '__main__':
    app.run_server(debug=True)

对应的剩余文件中的信息如下:(api.py和api.ipynb文件暂时没有内容)
在这里插入图片描述

3.3 header.py文件完善

该文件的功能就是显示项目标题,并居中,设置相对简答,全部代码如下。

from dash import html

def HeaderInfo():
    return html.Div(
        [
            html.H1('World Suicides Data')
        ]
    )

保存文件后,运行index.py,提示点击网址:http://127.0.0.1:8050/,刷线页面后,输出结果如下。
在这里插入图片描述

3.4 api.py/api.ipynb文件完善

其中api.py文件是为提供数据接口,api.iypnb文件方便进行数据处理和调式工作。下方左侧筛选的依据有国家、年份和年龄范围,所以针对此条件先在api.ipynb文件中进行数据处理,数据文件已放置在该项目下的data文件夹中。首先切换程序的执行路径,利用os.chdir()函数,输入当前项目所在的文件路径,然后在读入数据文件,代码及输出结果如下。
在这里插入图片描述

3.4.1 获取Dropdown组件中的下拉标签信息

获取国家/地区的唯一值,并去除缺失值None,代码如下。

#获取国家信息的唯一值
country_ls = df['country'].unique().tolist()

#检验列表中是否存在缺失值None
country_ls.count(None)

输出结果如下。
在这里插入图片描述

3.4.2 获取Rangeslider组件中的时间区间

数据时间跨度的获取,只需要求解出year字段中的最小值和最大值即可
在这里插入图片描述

3.4.3 获取Checklist组件中的年龄划分

年龄分组获取即是对age字段进行唯一值的获取。在输出的结果中如果使用列表的sort()排序功能,发现年龄分组字段是按照字符串的规则进行排序,先比对第一个字符的大小,如果第一个字符相同, 再比较第二个字符,以此类推。但是排序的结果不满足需要,因此可借助python中自带的sorted()函数,自定义排序规则,代码如下。

#获取年龄分组情况
age = df['age'].unique().tolist()

#使用列表的排序功能
age.sort()

#借助sorted()函数进行自定义排序规则设置
age_ordered = sorted(age,key=lambda x: int(x.split('-')[0]) if '-' in x else int(x[:2]))

输出结果如下。
在这里插入图片描述

数据成功获取后,把此部分代码转移到api.py文件中,此时该文件中的全部代码如下。

#切换程序的执行路径
import os
os.chdir('d:/Data Science/plotly学习/个人/【11. World suicide rate】Dropdown-Rangedlider-checklist-scatter')

#将文件数据读入到python中
import pandas as pd
df = pd.read_csv('data/suicide rates.csv')


#获取国家信息的唯一值,需要核实是否存在缺失值None
country_ls = df['country'].unique().tolist()

#获取数据的时间跨度
year_min,year_max = df['year'].min(),df['year'].max()

#获取年龄分组情况
age = df['age'].unique().tolist()

#借助sorted()函数进行自定义排序规则设置
age_ordered = sorted(age,key=lambda x: int(x.split('-')[0]) if '-' in x else int(x[:2]))

3.5 layoutleft.py文件完善

3.5.1 设置Dropdown组件

该文件的功能就是设置三个筛选的组件,首先完善第一个Dropdown组件,导入api.py中的全部数据变量,然后设置文字提醒,组件标签信息和id,代码如下。

from dash import html,dcc
from api import country_ls,year_min,year_max,age_ordered


def DropdownInfo():
    return html.Div(
        [
            html.H3('Select Country:'),
            dcc.Dropdown(
                country_ls,
                'Japan',
                id='dpd'
                )
        ]
    )

保存文件后,刷新页面,输出的内容如下。
在这里插入图片描述

3.5.2 设置Rangeslider组件

可以直接把项目9中的Rangeslider组件设置的代码直接复制粘贴过来,然后修改里面的起始值和id即可,代码如下。

def RangeSliderInfo():
   
    return html.Div(
        [
            html.H3('Select Year:'),
            dcc.RangeSlider(
                year_min,year_max,1,
                marks=None,
                value=[1995,2005],
                tooltip={"placement": "bottom", "always_visible": True},
                id='rangeslider',
            )
        ]
    )

保存文件后,刷新网址,此时页面输出结果如下。
在这里插入图片描述

3.5.3 设置Checklist组件

第一次使用Checklist组件,可以参考官网示例,如下。其中第一个列表里面包含了所有的内容,第二个列表是默认选择的值。
在这里插入图片描述

应用到项目中,丰富代码,如下。

def ChecklistInfo():
    return html.Div(
        [
            html.H3('Select Platform:'),
            dcc.Checklist(
                age_ordered,
                ['35-54 years','55-74 years'],
                id = 'checklist'
            )
        ]
    )

保存文件后,刷新网址,此时页面输出结果如下。
在这里插入图片描述

3.6 layoutright.py文件完善

该文件的功能是根据左侧的筛选条件进行散点图绘制,plotly绘制散点图官网示例,如下。
在这里插入图片描述
首先获取图表展示的数据,即按照国家、时间、年龄分组汇总求和的数据,形成一个新的数据集,方便在绘制图形时直接调用,代码及输出结果如下。
在这里插入图片描述
然后把此部分代码转移到api.py文件中并导入到layoutright.py文件中,再按照官网示例完善scatter图形绘制。

from dash import Input,Output,dcc
from app import app
import plotly.graph_objects as go
from api import suicide_df

def Scatterchart():
    return dcc.Graph(id='scatter',config={'displayModeBar': False})

@app.callback(
    Output('scatter','figure'),
    [Input('dpd','value'),Input('rangeslider','value'),Input('checklist','value')]
)
def update(select_country, slider_year, radio_items):
    #print(select_country, slider_year, radio_items)
    df = suicide_df[(suicide_df['country'] == select_country) & 
                        (suicide_df['year'] >= slider_year[0]) & 
                        (suicide_df['year'] <= slider_year[1]) & 
                        (suicide_df['age'].isin(radio_items))]
    
    fig = go.Figure(
        go.Scatter(
                    x=df['year'],
                    y=df['suicides_no'],
                    text = df['sex'],
                    textposition = 'top center',
                    mode = 'markers + text',
                    marker = dict(
                        size = df['suicides_no'] / 250,
                        color = df['suicides_no'],
                        colorscale = 'HSV',
                        showscale = False,
                        line = dict(
                            color = 'MediumPurple',
                            width = 2
                        )),
                    hoverinfo='text',
                    hovertext=
                    '<b>Country</b>: ' + df['country'].astype(str) + '<br>' +
                    '<b>Age</b>: ' + df['age'].astype(str) + '<br>' +
                    '<b>Sex</b>: ' + df['sex'].astype(str) + '<br>' +
                    '<b>Year</b>: ' + df['year'].astype(str) + '<br>' +
                    '<b>Population</b>: ' + [f'{x:,.0f}' for x in df['population']] + '<br>' +
                    '<b>Suicides/100k pop</b>: ' + [f'{x:,.0f}' for x in df['suicides/100k pop']] + '<br>' +
                    '<b>Suicides</b>: ' + [f'{x:,.0f}' for x in df['suicides_no']] + '<br>'
              )
    )
    fig.update_layout(
        margin=dict(
            l=0,
            r=0,
            t=0,
            b=0
        )
    )
    return fig

保存文件后,刷新网址,此时页面输出结果如下。
在这里插入图片描述

4 样式修改

4.1 整体样式修改

在assets文件夹下新建一个setting.css文件,设置整体风格。主要是背景、边缘和字体颜色的设置。
在这里插入图片描述

此时页面样式输出如下。
在这里插入图片描述

4.2 header.py文件中样式修改

只有一个主题文字,需要做的就是进行居中处理即可。根据实际显示,又调整了一下文字和下方内容的边距。
在这里插入图片描述

4.3 layoutleft.py文件中样式修改

首先把项目10中的卡片容器应用到这里的左右两部分。由于项目的主题背景是偏黑,所以颜色上修改一下,指定为黑色调颜色。
在这里插入图片描述

然后应用到左侧栏中,需要注意该属性添加的位置是在index.py文件中,如下。
在这里插入图片描述
保存文件后,刷新网址,此时页面输出结果如下。
在这里插入图片描述

接着修改组件颜、间距等属性。先调整Dropdown组件的属性,直接把项目10中此属性全部复制过来,然后改一下背景颜色和字体颜色即可,代码如下。

/* width */
::-webkit-scrollbar {
    width: 10px !important;
    display: block !important;
  }


/* Track */
::-webkit-scrollbar-track {
    background: #232c37 !important;
    border-radius: 10px !important;
    display: block !important;
    }
    
/* Handle */
::-webkit-scrollbar-thumb {
background: #363535 !important;
}

/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: white !important;
}

#dpd * {
    background-color: #191a1a !important;
    color: #f7f8f9 !important;
    font-size: 10px !important;
}

.Select-control{
    border: 3px solid #323844 !important;
}

.Select-menu-outer{
    overflow: hidden !important;
    border-color: #373838 !important;
}

保存文件后,刷新网址,此时页面输出结果如下。
在这里插入图片描述

然后调整三个组件直接的间距,代码修改如下。
在这里插入图片描述

对于Rangeslider组件中的滑块中间的区域颜色以及按钮的边缘颜色也可以进行设置,这里按照自己的想法进行修改,代码如下。

.rc-slider-track{
    background-color: rgb(234, 13, 112) !important;
}

.rc-slider-handle{
    border-color: rgb(234, 13, 112) !important;
}

最后是关于Checklist组件的设置,当前版本中默认就是横向排布,尝试了很多参数后都没有办法实现垂直排列,如下。
在这里插入图片描述

那就只能自己自定义属性,设置一个columns属性,设置组件的宽度为三分之一,然后左对齐,设置适当的边距,完成目标样式,代码及文件修改内容如下。此处显示为全部添加指定参数时的使用方法,也可以采用最初的简写方式。

在这里插入图片描述

保存文件后,刷新网址,此时页面输出结果如下。
在这里插入图片描述

4.4 layoutright.py文件中样式修改

在项目10中已经处理过plotly绘制图形背景与项目主题背景融合的问题,添加两行代码即可解决,但是要注意设置一下字体颜色,不然文字标注就看不清楚了,全部代码如下。

from dash import Input,Output,dcc,html
from app import app
import plotly.graph_objects as go
from api import suicide_df

def Scatterchart():
    return html.Div(id = 'content')

@app.callback(
    Output('content','children'),
    [Input('dpd','value'),Input('rangeslider','value'),Input('checklist','value')]
)
def update(select_country, slider_year, radio_items):
    print(select_country, slider_year, radio_items)
    df = suicide_df[(suicide_df['country'] == select_country) & 
                        (suicide_df['year'] >= slider_year[0]) & 
                        (suicide_df['year'] <= slider_year[1]) & 
                        (suicide_df['age'].isin(radio_items))]
    
    fig = go.Figure(
        go.Scatter(
                    x=df['year'],
                    y=df['suicides_no'],
                    text = df['sex'],
                    textposition = 'top center',
                    mode = 'markers + text',
                    marker = dict(
                        size = df['suicides_no'] / 250,
                        color = df['suicides_no'],
                        colorscale = 'HSV',
                        showscale = False,
                        line = dict(
                            color = 'MediumPurple',
                            width = 2
                        )),
                    hoverinfo='text',
                    hovertext=
                    '<b>Country</b>: ' + df['country'].astype(str) + '<br>' +
                    '<b>Age</b>: ' + df['age'].astype(str) + '<br>' +
                    '<b>Sex</b>: ' + df['sex'].astype(str) + '<br>' +
                    '<b>Year</b>: ' + df['year'].astype(str) + '<br>' +
                    '<b>Population</b>: ' + [f'{x:,.0f}' for x in df['population']] + '<br>' +
                    '<b>Suicides/100k pop</b>: ' + [f'{x:,.0f}' for x in df['suicides/100k pop']] + '<br>' +
                    '<b>Suicides</b>: ' + [f'{x:,.0f}' for x in df['suicides_no']] + '<br>'
              )
    )
    fig.update_layout(
        paper_bgcolor='#202020',
        plot_bgcolor='#202020',
        font=dict(
        # family="Lato",
        size=14,
        color="white"),
        margin=dict(
            l=0,
            r=0,
            t=0,
            b=0
        ),

        xaxis=dict(title='<b>Year</b>',
                        color='white',
                        showline=True,
                        showgrid=False,
                        linecolor='white',
                        zeroline=False
                        
                ),

        yaxis=dict(
                title= '<b>Suicides</b>',
                color= 'white',
                showline= False,
                showgrid= True,
                gridcolor='#5a5a5a',
                tickfont={
                    'family': 'Aerial',
                    'color': 'white',
                    'size': 12
                },
                zeroline=False
        )
 
    )
    return [
            html.H3(f'Suicide Datas: {select_country}',style={'textAlign':'center'}),
            dcc.Graph(figure=fig,config={'displayModeBar': False})
        ]

保存文件后,刷新网址,此时页面输出结果如下。
在这里插入图片描述

5 小bug

一不小心发现Checklist组件中的标签顺序不对,仔细检查一下发现在指定时又进行了sorted()一下,于是干脆就直接使用最初简单的样式(或者直接删除sorted函数也可),修改及输出对比如下。
在这里插入图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lys_828

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值