循序渐进,学会用pyecharts绘制瀑布图

瀑布图简介

瀑布图(Waterfall Plot)是由麦肯锡顾问公司所独创的图表类型,因为形似瀑布流水而称之为瀑布图。

瀑布图采用绝对值与相对值结合的方式,适用于表达多个特定数值之间的数量变化关系。当用户想表达两个数据之间数量的演变过程时,可以使用瀑布图。当用户想表达一连续的数值加减关系时,也可以使用瀑布图。

这种效果的图形能够在反映数据多少的同时,更直观地反映出数据的增减变化过程。

瀑布图经常用于财务分析,以了解多种因素对特定对象的正面和负面影响。可以显示基于时间或基于类别的效果,基于类别的图表表示费用或销售额的收益或损失,基于时间的图表表示一段时间内的收益或损失。

在Python中,可以使用pyecharts库中绘制柱状图的组件 Bar 实现瀑布图,本文就循序渐进地介绍一步步将柱状图演变成瀑布图。

绘制柱状图

绘图前需要先安装pyecharts库,如果你还没有安装,请先用 pip install pyecharts 安装。
本文绘图使用虚拟数据,假设你是一个老板,本文的数据表示2023年你公司的总人数、招聘人数和离职人数。你要求在展示每个月总人数的同时,还可以清晰地看出人数变化。

数据如下:

month = [f'2023-0{i}' for i in range(1, 10)] + [f'2023-{i}' for i in range(10, 13)]
# 每月总人数
total = [50, 48, 42, 48, 58, 63, 61, 65, 58, 63, 69, 67]
# 每月入职人数
entry = [0, 2, 12, 10, 5, 0, 4, 0, 10, 8, 3, 0]
# 每月离职人数
resign = [2, 8, 6, 0, 0, 2, 0, 7, 5, 2, 5, 1]

绘制柱状图使用pyecharts中的 Bar 组件,先初始化一个 Bar 对象,调用 add_xaxis()方法添加横轴数据,链式调用add_yaxis()方法添加纵轴数据。再链式调用set_global_opts()设置坐标轴格式、字体等,最后链式调用render()方法将图形渲染到HTML文件中,可以用浏览器打开绘图结果。

from pyecharts.charts import Bar
from pyecharts import options as opts

# 柱状图
bar = Bar(init_opts=opts.InitOpts(width='800px', height='500px'))
bar.add_xaxis(month).add_yaxis(
    '各月总人数', y_axis=total, category_gap=2
).set_global_opts(
    xaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=8, color='green', font_weight='bolder')
    ), yaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=10, color='blue', font_weight='bolder')
    )
).render('people_total.html')

mpAndroidChart柱状图瀑布柱状图 瀑布图和柱状图_信息可视化

此时绘制了一个普通的柱状图,展示了每个月的员工总人数。但是每个月的入职人数和离职人数没有展示在图形中。

绘制并列柱状图

要将多组数据的柱状图并列展示,可以多次链式调用add_yaxis()方法添加多组数据。

# 并列柱状图
bar = Bar(init_opts=opts.InitOpts(width='800px', height='500px'))
bar.add_xaxis(month).add_yaxis(
    '各月总人数', y_axis=total, gap=0, category_gap=0,
).add_yaxis(
    '各月入职人数', y_axis=entry, gap=0, category_gap=0
).add_yaxis(
    '各月离职人数', y_axis=resign, gap=0, category_gap=0
).set_global_opts(
    xaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=8, color='green', font_weight='bolder')
    ), yaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=10, color='blue', font_weight='bolder')
    )
).render('people_total_and_other.html')

mpAndroidChart柱状图瀑布柱状图 瀑布图和柱状图_信息可视化_02

将总人数、入职人数、离职人数全部添加到柱状图中,三组数据都展示了。

不过,这三组数据的大小变化是有关系的,会相互影响,并列的柱状图看不出来彼此之间的关系。

绘制堆叠柱状图

并列展示的柱状图不符合要求,所以尝试将柱状图堆叠起来展示。堆叠柱状图的实现方法是在每个add_yaxis()方法中设置 stack 参数,要将哪几组柱状图堆叠在一起,就给它们的 stack 参数设置一样的值(这个值可以自定义)。

# 堆叠柱状图
bar = Bar(init_opts=opts.InitOpts(width='800px', height='500px'))
bar.add_xaxis(month).add_yaxis(
    '各月总人数', y_axis=total, stack='人数', category_gap=2,
).add_yaxis(
    '各月入职人数', y_axis=entry, stack='人数', category_gap=2
).add_yaxis(
    '各月离职人数', y_axis=resign, stack='人数', category_gap=2
).set_global_opts(
    xaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=8, color='green', font_weight='bolder')
    ), yaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=10, color='blue', font_weight='bolder')
    )
).render('people_total_stack.html')

mpAndroidChart柱状图瀑布柱状图 瀑布图和柱状图_pyecharts瀑布图_03

不难发现,将柱状图堆叠在一起可以展示“叠加”的效果。不过,本文中的数据不完全适合叠加展示,入职人数是在总人数的基础上相加,离职人数则要在总人数的基础上相减。堆叠图只能展示不断叠加,还要在此基础上把减少的效果也展示出来,所以需要做进一步的改造。

根据前面对瀑布图的介绍,当用户想表达一连续的数值加减关系时,可以使用瀑布图。下面就来看如何实现。

绘制瀑布图

根据瀑布图的特征,它采用绝对值与相对值结合的方式,适用于表达数个特定数值之间的数量变化关系。所以在绘制瀑布图前,要先对数据做一定的改造,能体现绝对值和相对值的关系。

每个月的入职人数和离职人数计算的绝对值就是每个月的增加人数或减少人数。如果入职人数大于离职人数,则这个月增加人数为正数、无减少人数(用’-‘表示,方便绘图),反之,如果入职人数小于离职人数,则增加人数为’-‘,减少人数为正数,入职人数和离职人数相等则增加人数、减少人数都为’-'。

每个月的入职人数和总人数,离职人数和总人数计算的相对值是每个月稳定的人数。如果某个月人数增加,则这个月的稳定人数就是月初的总人数,如果某个月人数减少,则这个月的稳定人数就是月初的总人数减掉减少的人数。

举例:2023年1月,总人数50,入职0,离职2,则这个月减少2人,稳定人数为50-2=48人。2023年3月,总人数42,入职12,离职6,则这个月增加6人,稳定人数为42人。同理可以推出其他所有月的数据。

改造好数据后,开始绘制瀑布图,瀑布图的代码与堆叠图大部分一样。瀑布图主要是体现数据变化的部分,所以一般都将“数据稳定”的部分隐藏(rgba颜色值中将a通道设置为0),本文用rgb颜色值把“稳定数据”设置成灰色。

# 瀑布图
# 稳定人数
fixed = [48, 42, 42, 48, 58, 61, 61, 58, 58, 63, 67, 66]
# 增加人数
add = ['-', '-', 6, 10, 5, '-', 4, '-', 5, 6, '-', '-']
# 减少人数
reduce = [2, 6, '-', '-', '-', 2, '-', 7, '-', '-', 2, 1]
bar = Bar(init_opts=opts.InitOpts(width='800px', height='500px'))
bar.add_xaxis(month).add_yaxis(
    '各月稳定人数', y_axis=fixed, category_gap=2,
    stack="人数", itemstyle_opts=opts.ItemStyleOpts(color="rgb(240,240,240)")
).add_yaxis(
    '各月增加人数', y_axis=add, stack='人数', category_gap=2
).add_yaxis(
    '各月减少人数', y_axis=reduce, stack='人数', category_gap=2
).set_global_opts(
    xaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=8, color='green', font_weight='bolder')
    ), yaxis_opts=opts.AxisOpts(
        axislabel_opts=opts.LabelOpts(font_size=10, color='blue', font_weight='bolder')
    )
).render('people_total_waterfall.html')

mpAndroidChart柱状图瀑布柱状图 瀑布图和柱状图_python瀑布图_04

经过以上几个步骤的演进,完成了瀑布图的绘制,可以很清晰地看到每个月人数的增加和减少,完美展示了数据变化的过程。这样一步一步地调整和演进,相信看完后你已经知道如何绘制瀑布图了,欢迎一键三连。

参考文档:
[1] pyecharts官方文档:https://gallery.pyecharts.org/#/Bar/README