【python实战】pyecharts时间轮播图——结婚了么?

2021-04-21  本文已影响0人  Hobbit的理查德

最近翻到好久之前收藏的一个关于绘制时间轮播图的帖子,就想趁着兴头,找点时间实现一下。

本来是打算拿之前爬取的北京二手房的数据结果展示,弄完了之后没啥大感觉,就想着换个主题的数据。

正好翻到了民政部的关于2007-2020年的全国及各省份的各个季度的结婚和离婚登记数的数据,就想着那这个数据练一练吧。

一、代码及结果Part

数据整理到excel后是这样的:

marriagePic.png

1、数据准备

所有要导入的包

import pandas as pd
import os
from pyecharts.charts import Line, Map, Bar, Timeline, Grid
from pyecharts import options as opts
from pyecharts.globals import ThemeType

首先,进行数据准备。

①每个季度的数据是指截止该季度的总数,因此,计算第2,3,4季度的增量,需要用后一季度的数减去前一季度的数,得到每年每个季度结婚登记和离婚登记的当个季度增加的数量

②计算每年的新增夫妻数,即用每年第4个季度的结婚登记数减去离婚登记数。

③将这种宽数据转为长数据,并进行分列,地区名清理,单位换算成万对等。

current_dir = os.getcwd()
df = pd.read_excel(current_dir+'\\'+'全国结婚离婚数据new.xlsx')

# 计算每年各个季度当季度增加数量
for i in range(2007,2021):
    for j in range(1,4):
        colname_jie = str(i)+'年第'+str(j+1)+'季度结婚登记新增'
        colname_li  = str(i)+'年第'+str(j+1)+'季度离婚登记新增'

        df[colname_jie] = df[str(i)+'年第'+str(j+1)+'季度结婚登记']-df[str(i)+'年第'+str(j)+'季度结婚登记']
        df[colname_li]  = df[str(i)+'年第'+str(j+1)+'季度离婚登记']-df[str(i)+'年第'+str(j)+'季度离婚登记']

# 计算每年新增夫妻数量
for i in range(2007,2021):
    colname = str(i)+'年新增夫妻数量'
    df[colname] = df[str(i)+'年第4季度结婚登记']-df[str(i)+'年第4季度离婚登记']

# print(df)

# 宽数据转长数据
long_df = df.melt(id_vars = ['地区'], var_name = '年份季度状态', value_name = 'couple_num')

# 拆分列
long_df['年份']=long_df['年份季度状态'].str[:4]
long_df['季度']=long_df['年份季度状态'].str[5:9]
long_df['状态']=long_df['年份季度状态'].str[9:11]
long_df['couple_num(万对)']=round(long_df['couple_num']/10000,2)

# 地区替换
long_df['地区']=long_df['地区'].str.replace('市','')
long_df['地区']=long_df['地区'].str.replace('省','')
long_df['地区']=long_df['地区'].str.replace('自治区','')
long_df['地区']=long_df['地区'].str.replace('壮族','')
long_df['地区']=long_df['地区'].str.replace('回族','')
long_df['地区']=long_df['地区'].str.replace('维吾尔','')

# print(long_df['地区'].unique())
print(long_df.head(31))

数据整理之后,长成这样:

marriagePicLong.png

2、2007-2020年全国结婚和离婚登记情况

先做个简单的折线图Line,看看这14年全国结婚和离婚登记数量情况变化趋势。

# 选出第4季度的数据
nation_df=long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第4季度') & (long_df['年份季度状态'].str.contains('新增')==0)]
nation_df.sort_values(by=['状态','年份'],ascending=(False, True), inplace=True, ignore_index=True)
nation_df['couple_num(万对)']=round(nation_df['couple_num(万对)'],2)

nation_jie=nation_df[nation_df['状态']=='结婚']
nation_li=nation_df[nation_df['状态']=='离婚']

# 准备数据
yearls=list(nation_jie['年份'])
num_jie=list(nation_jie['couple_num(万对)'])
num_li=list(nation_li['couple_num(万对)'])

# 做折线图
c = (
    Line()
    .add_xaxis(yearls)
    .add_yaxis("结婚对数(万对)", num_jie, is_smooth=True)
    .add_yaxis("离婚对数(万对)", num_li, is_smooth=True)
    .set_series_opts(
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=True, position = 'top'),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="2007-2020年全国结婚和离婚登记(万对)"),
        xaxis_opts=opts.AxisOpts(
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
            is_scale=False,
            boundary_gap=False,
        ),
        legend_opts=opts.LegendOpts(pos_right = 20, orient = 'Vertical')
    )
    .render("2007-2020年全国结婚和离婚登记(万对).html")
)

结果如下图所示。

2007-2020年全国结婚和离婚登记(万对).gif

2013年结婚登记达到顶峰,之后就逐渐下降。而离婚登记则是逐年增加,2020年还有些许回落。

由此可见,存续期的夫妻对数(红色区域)也是在2013年之后逐渐减少了。

3、2007-2020年各个季度全国结婚和离婚登记情况

接着,做个折线图Line+时间轮播图Timeline,看看每个季度的全国结婚和离婚登记情况随年份的变化。

# 选出各季度新增数据
nation_first_jie=long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第1季度') & (long_df['状态']=='结婚')]
nation_first_li =long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第1季度') & (long_df['状态']=='离婚')]

nation_second_jie=long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第2季度') & (long_df['状态']=='结婚') & (long_df['年份季度状态'].str.contains('新增'))]
nation_second_li =long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第2季度') & (long_df['状态']=='离婚') & (long_df['年份季度状态'].str.contains('新增'))]

nation_third_jie=long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第3季度') & (long_df['状态']=='结婚') & (long_df['年份季度状态'].str.contains('新增'))]
nation_third_li =long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第3季度') & (long_df['状态']=='离婚') & (long_df['年份季度状态'].str.contains('新增'))]

nation_fourth_jie=long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第4季度') & (long_df['状态']=='结婚') & (long_df['年份季度状态'].str.contains('新增'))]
nation_fourth_li =long_df[(long_df['地区']=='全国合计') & (long_df['季度']=='第4季度') & (long_df['状态']=='离婚') & (long_df['年份季度状态'].str.contains('新增'))]

# 数据准备
first_jie_num=list(nation_first_jie['couple_num(万对)'])
first_li_num =list(nation_first_li['couple_num(万对)'])

second_jie_num=list(nation_second_jie['couple_num(万对)'])
second_li_num =list(nation_second_li['couple_num(万对)'])

third_jie_num=list(nation_third_jie['couple_num(万对)'])
third_li_num =list(nation_third_li['couple_num(万对)'])

fourth_jie_num=list(nation_fourth_jie['couple_num(万对)'])
fourth_li_num =list(nation_fourth_li['couple_num(万对)'])

yearls = list(nation_first_jie['年份'])


# timeline图

Line1 = (
    Line()
    .add_xaxis(yearls)
    .add_yaxis("结婚对数(万对)", first_jie_num, is_smooth=True)
    .add_yaxis("离婚对数(万对)", first_li_num, is_smooth=True)
    .set_series_opts(
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=True, position = 'top'),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="2007-2020年全国结婚和离婚登记(万对)——第1季度"),
        xaxis_opts=opts.AxisOpts(
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
            is_scale=False,
            boundary_gap=False,
        ),
        yaxis_opts=opts.AxisOpts(max_=500),
        legend_opts=opts.LegendOpts(pos_right = 20, orient = 'Vertical')
    )
)

Line2 = (
    Line()
    .add_xaxis(yearls)
    .add_yaxis("结婚对数(万对)", second_jie_num, is_smooth=True)
    .add_yaxis("离婚对数(万对)", second_li_num, is_smooth=True)
    .set_series_opts(
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=True, position = 'top'),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="2007-2020年全国结婚和离婚登记(万对)——第2季度"),
        xaxis_opts=opts.AxisOpts(
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
            is_scale=False,
            boundary_gap=False,
        ),
        yaxis_opts=opts.AxisOpts(max_=500),
        legend_opts=opts.LegendOpts(pos_right = 20, orient = 'Vertical')
    )
)

Line3 = (
    Line()
    .add_xaxis(yearls)
    .add_yaxis("结婚对数(万对)", third_jie_num, is_smooth=True)
    .add_yaxis("离婚对数(万对)", third_li_num, is_smooth=True)
    .set_series_opts(
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=True, position = 'top'),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="2007-2020年全国结婚和离婚登记(万对)——第3季度"),
        xaxis_opts=opts.AxisOpts(
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
            is_scale=False,
            boundary_gap=False,
        ),
        yaxis_opts=opts.AxisOpts(max_=500),
        legend_opts=opts.LegendOpts(pos_right = 20, orient = 'Vertical')
    )
)

Line4 = (
    Line()
    .add_xaxis(yearls)
    .add_yaxis("结婚对数(万对)", fourth_jie_num, is_smooth=True)
    .add_yaxis("离婚对数(万对)", fourth_li_num, is_smooth=True)
    .set_series_opts(
        areastyle_opts=opts.AreaStyleOpts(opacity=0.5),
        label_opts=opts.LabelOpts(is_show=True, position = 'top'),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="2007-2020年全国结婚和离婚登记(万对)——第4季度"),
        xaxis_opts=opts.AxisOpts(
            axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
            is_scale=False,
            boundary_gap=False,
        ),
        yaxis_opts=opts.AxisOpts(max_=500),
        legend_opts=opts.LegendOpts(pos_right = 20, orient = 'Vertical')
    )
)
timeline=Timeline(init_opts=opts.InitOpts(width="900px", height="500px"))
timeline.add(Line1,'第1季度')
timeline.add(Line2,'第2季度')
timeline.add(Line3,'第3季度')
timeline.add(Line4,'第4季度')
timeline.add_schema(
        play_interval=2500,          # 轮播速度
        is_timeline_show=True,     # 是否显示 timeline 组件
        is_auto_play=True,          # 是否自动播放
    )
timeline.render('2007-2020年各个季度全国结婚和离婚登记(万对).html')

结果如下图。

2007-2020年各个季度全国结婚和离婚登记(万对).gif

看起来,人们普遍喜欢第1季度和第4季度结婚,毕竟节假日多。其中,2013年第1季度的结婚登记数量真的是“异军突起”,百度了下,发现原来:2013年1月4日是个好日子……

news1.png

但是,总的来看,人们离婚是不大挑时候的,各季度数量在当年变化不大。

4、各省份不同年份的结婚登记情况

接着,绘制地图Map+条形图Bar+时间轮播图Timeline,看看不同省份不同年份的结婚登记情况。

# 绘制地图Map+条形图Bar+时间轮播图Timeline
def map_bar(province_df,titlecontent,htmltitle,rangecolor,titlecolor,barmaxvalue,barinterval):

    t = Timeline(init_opts=opts.InitOpts(width="1200px", height="700px"))  # 定制主题
    for i in range(2007,2021):
        sub = province_df[province_df["年份"]==str(i)]
        min_data=min(list(sub['couple_num(万对)']))
        max_data=max(list(sub['couple_num(万对)']))
        map_chart = (
            Map(init_opts=opts.InitOpts(width='300px', height='300px'))
            .add(
                series_name="",
                data_pair=[list(z) for z in zip(list(sub['地区']),list(sub['couple_num(万对)']))],
                zoom=1,
                center=[119.5, 34.5],
                is_map_symbol_show=False,
            )
            .set_global_opts(
                title_opts=opts.TitleOpts(
                    title="" + str(i) + titlecontent + "(单位:万对)",
                    pos_left="center",
                    pos_top="top",
                    title_textstyle_opts=opts.TextStyleOpts(
                        font_size=25, color=titlecolor
                    ),
                ),
                tooltip_opts=opts.TooltipOpts(
                    is_show=False,
                ),
                visualmap_opts=opts.VisualMapOpts(
                    is_calculable=True,
                    dimension=0,
                    pos_left="2%",
                    pos_bottom="20%",
                    range_text=["", ""],
                    range_color=rangecolor,
                    textstyle_opts=opts.TextStyleOpts(color="black",font_size=15),
                    min_=min_data,
                    max_=max_data,
                ),
            )
        )
        bar = (
            Bar() #初始化设置
            .add_xaxis(list(sub['地区']))         # x轴数据
            .add_yaxis('登记数量(万对)', list(sub['couple_num(万对)']))   # y轴数据
            .reversal_axis()     # 翻转
            .set_global_opts(    # 全局配置项
                xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(is_show=False),
                    splitline_opts=opts.SplitLineOpts(is_show=True),max_=barmaxvalue,interval = barinterval,
                    axisline_opts=opts.AxisLineOpts(is_show=False),
                    axistick_opts=opts.AxisTickOpts(is_show=False)),
                yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(interval=0)),
                visualmap_opts=opts.VisualMapOpts(   #如果不加这个的话,地图效果出不来
                    is_calculable=True,
                    dimension=0,
                    pos_left="2%",
                    pos_bottom="20%",
                    range_text=["", ""],
                    range_color=rangecolor,
                    textstyle_opts=opts.TextStyleOpts(color="black",font_size=15),
                    min_=min_data,
                    max_=max_data,
                ),
                legend_opts=opts.LegendOpts(is_show = False)
            )
            .set_series_opts(    # 系列配置项
                label_opts=opts.LabelOpts(position="right"))
            .set_colors('#D2691E')
        )
        
        grid_chart = (
            Grid()
            .add(
                bar,
                grid_opts=opts.GridOpts(
                    pos_left="70%", pos_right="10%", pos_top="10%", pos_bottom="10%",is_contain_label=False
                ),
            )
            .add(map_chart, grid_opts=opts.GridOpts())
        )

        t.add(grid_chart,str(i))


    t.add_schema(
            orient="vertical",
            is_auto_play=True,
            is_inverse=True,
            play_interval=1000,
            pos_left="null",
            pos_right="0",
            pos_top="10",
            pos_bottom="10",
            width="60",
            label_opts=opts.LabelOpts(is_show=True, interval=0,color="Black",font_size = 15,font_weight="bold"),
        )
    
    t.render(htmltitle+'.html')
    
# 各省份不同年份的结婚登记数量(万对)
province_jie=long_df[(long_df['地区']!='全国合计') & (long_df['季度']=='第4季度') & (long_df['状态']=='结婚') & (long_df['年份季度状态'].str.contains('新增')==0)]
province_jie.sort_values(by=['年份','couple_num(万对)'],ascending=(True,True), inplace=True, ignore_index=True)

titlecontent = "年各省份的结婚登记数量"
htmltitle = "各省份不同年份的结婚登记数量"

rangecolor = ['DeepSkyBlue','Orange','Red']

titlecolor='Red'

barmaxvalue,barinterval=140,20

map_bar(province_jie,titlecontent,htmltitle,rangecolor,titlecolor,barmaxvalue,barinterval)

结果如下图所示。

各省份不同年份的结婚登记数量.gif

各个省份也是不断地往回缩的(条形图中),人口大省自然数量多了(地图中),而且,波动(颜色变化)也是比较明显。

5、各省份不同年份的离婚登记情况

# 各省份不同年份的离婚登记数量(万对)
province_li=long_df[(long_df['地区']!='全国合计') & (long_df['季度']=='第4季度') & (long_df['状态']=='离婚') & (long_df['年份季度状态'].str.contains('新增')==0)]
province_li.sort_values(by=['年份','couple_num(万对)'],ascending=(True,True), inplace=True, ignore_index=True)

titlecontent = "年各省份的离婚登记数量"
htmltitle = "各省份不同年份的离婚登记数量"

rangecolor = ['DeepSkyBlue','Orange','Red'][::-1]

titlecolor='DeepSkyBlue'

barmaxvalue,barinterval=35,10

map_bar(province_li,titlecontent,htmltitle,rangecolor,titlecolor,barmaxvalue,barinterval)

结果如下图所示。

各省份不同年份的离婚登记数量.gif

各个省份也是一直在往右增加(条形图中),尤其是东部沿海,增加的(颜色往蓝色变化)比较明显(地图中)。

6、各省份不同年份的新增夫妻情况

# 各省份不同年份的新增夫妻数(万对)
province_add = long_df[(long_df['地区']!='全国合计') & (long_df['状态']=='数量')]
province_add.sort_values(by=['年份','couple_num(万对)'],ascending=(True,True), inplace=True, ignore_index=True)

titlecontent = "年各省份新增夫妻数"
htmltitle = "各省份不同年份的新增夫妻数"

rangecolor = ['DeepSkyBlue','Orange','Red']

titlecolor='Orange'

barmaxvalue,barinterval=120,20

map_bar(province_add,titlecontent,htmltitle,rangecolor,titlecolor,barmaxvalue,barinterval)

结果如下图所示。

各省份不同年份的新增夫妻数.gif

各个省份往回缩得明显呐(条形图中),尤其是东部沿海,减少(颜色往蓝色变化)比较明显(地图中)。

二、碎碎念Part

看了上面的结果,每个人有每个人的感受,有的人会担忧,有的人会欣喜,有的人会感到安慰,有的人会感到孤独……大家自行解读就好。

在绘制这些图的时候,不禁就想起和郑老师之前讨论过或者聊到过的关于婚姻或感情的看法。

首先,婚姻是什么。对于我们俩人来说,婚姻更像是合伙经营一家两人的夫妻店,老板是我们自己,客户也是我们自己,产品就是我们俩人一起经历的事情以及积累的感情。

qq1.png qq2.png

在婚姻中的状态,两个人的感情由最开始的陌生人到恋人,到后来,在相处过程中,体验到各种感情状态,包括不限于夫妻,情人,朋友,兄弟,姐妹,亲人,师生,战友,同事等。

变身.gif

但同时,我们又很清楚,并没有谁离不开谁,如果经历了背叛或者两人再也不合适了,离婚也不丢人,两个人过得都痛苦硬过,才丢人吧。

企鹅.gif

毕竟,两个人在一起的生活状态就是,各种情绪状态都会被放大。开心的时候,总有个人跟你分享,放大你的开心;不开心的时候,很容易被另一个人捕捉到,一方面两个人都不开心了,另一方面,下次在不开心前又得想着收敛些。

摔倒.gif

一个人的决定和打算里总会顾忌到另一方。开心常有,争吵也有,妥协也有,尽在取舍。

如果对未来两个人的状态还有想象和期待,那就可以继续过下去。

郑老师经常会说一些关于老了之后的话,“你以后要是变成小老太太,我要在你身边陪你护着你”,“走在路上啊,有时候就会想到,我们俩都老了,想着还是我后走吧。”

我作为一个遇事就怂、消极主义倾向的人,会在两个人啥也没有的时候有勇气结婚,也不过只是觉得,“郑老师老了之后是个很好的老伴儿,即使变老的过程中,会有波折,那也能接受。”

老夫妻.gif

长大成年后,越来越发现,好像很多事情感觉像是到了年纪就可以顿悟一般地习得。

该恋爱了,就得知道如何当好恋人;

该结婚了,就得知道如何做好丈夫和妻子;

该生孩子了,就得准备好并知道如何做个好父母了……

但事实却并非如此,鸡飞狗跳是常态,平稳顺畅倒稀缺。

不过,不管怎么样,单身也好,恋爱也好,结婚也好,离婚也好,儿女成群也好,丁克到底也好,自己心里过得去最重要。

照镜子.gif
上一篇下一篇

猜你喜欢

热点阅读