一、什么是瀑布图
瀑布图用来展示初始值,经过多轮增减之后得到最终值,可以直观看到每一项对总量的贡献。
特点:
- 柱子从前一项的终点开始向上 / 向下延伸
- 正数向上,负数向下
- 一般用不同颜色区分:增加、减少、总计
matplotlib 本身没有内置瀑布图函数,需要我们手动计算每个柱子的底部位置来绘制。
二、瀑布图(Waterfall Chart)应用场景
1.财务分析
- 利润拆解:营业收入 → 减营业成本 → 减各项费用 → 加其他收益 → 减所得税 →净利润一眼看清:哪一项侵蚀利润、哪一项带来收益。
- 现金流分析(刚才示例):期初现金,加减经营、投资、融资现金流,得到期末现金。
- 预算差异分析:目标预算为基数,各项超支 / 节约,最后得到实际总额。
- 净资产变动:期初所有者权益,加上净利润、分红、股本变动,得到期末净资产。
2.业务指标归因分析(数据分析 / 运营)
用来做指标拆解,定位增长或下滑原因
- 营收拆解:上期营收 → 新增用户收入 + 老用户复购收入 - 用户流失损失 → 本期营收
- 用户量变化:期初用户数 + 新增用户 - 流失用户 = 期末用户
- GMV 拆解:基准 GMV + 活动增量 - 退款金额 = 最终 GMV
3.项目成本与投资测算
- 项目总投资测算:基础造价 + 设备采购 + 人工成本 - 补贴 / 优惠 = 项目总投入
- 投资收益测算:初始投入 + 每年收入 - 运营成本 = 净收益
4.供应链、库存管理
库存数量变动:期初库存 + 入库数量 - 出库数量 - 损耗 = 期末库存。
5. 工程 / 制造业:工程量、能耗分析
- 能耗:基准能耗 + 新增设备耗能 - 节能改造节省能耗 = 最终能耗。
三、不适合使用瀑布图的场景
- 只想看各部分占整体百分比→ 用饼图,不要瀑布图。
- 多组数据对比(5 个部门同时做瀑布对比会很乱),少量组别可以,多了不推荐。
- 分类没有先后加减逻辑,只是独立分类,不要强行用瀑布图。
对比:瀑布图 vs 其他图表
- 柱状图:直接对比独立类别大小,没有 “连续累加” 含义
- 饼图:静态构成占比,不能表达增减变化过程
- 瀑布图:专门表达从初始值,逐项加减,得到最终结果
四、完整代码 + 逐行讲解
python
import matplotlib.pyplot as plt import numpy as np # ---------------------- 1. 准备数据 ---------------------- # 标签:各项名称 labels = ["期初", "营收增加", "成本减少", "费用支出", "税收", "期末"] # 数值:期初是初始基数,后面是每一步变化量,最后一项为0(用来画总计) values = [100, 40, 10, -25, -15, 0] # 计算每个柱子的底部基线 base base = np.zeros(len(values)) for i in range(1, len(values)-1): base[i] = base[i-1] + values[i-1] # 最后一个柱子(期末总计),基线=前面所有累加和 base[-1] = base[-2] + values[-2] values[-1] = base[-1] # 总计柱子高度等于最终值 # ---------------------- 2. 设置颜色 ---------------------- colors = [] for i, v in enumerate(values): if i == 0: colors.append("#1f77b4") # 期初:蓝色 elif i == len(values)-1: colors.append("#ff7f0e") # 期末总计:橙色 elif v > 0: colors.append("#2ca02c") # 增加:绿色 else: colors.append("#d62728") # 减少:红色 # ---------------------- 3. 绘图 ---------------------- plt.figure(figsize=(10,6)) bars = plt.bar(labels, values, bottom=base, color=colors, edgecolor="black") # 在柱子上方添加数值标签 for bar in bars: height = bar.get_height() y_pos = bar.get_y() + height plt.text(bar.get_x() + bar.get_width()/2, y_pos, f"{height:.0f}", ha="center", va="bottom", fontsize=11) # ---------------------- 4. 美化图表 ---------------------- plt.title("瀑布图示例:现金流变化", fontsize=14) plt.ylabel("金额", fontsize=12) plt.grid(axis="y", alpha=0.3) plt.tight_layout() plt.show()五、核心原理讲解
plt.bar(x, height, bottom=base)
height:柱子高度(变化量)bottom:柱子底部的 y 坐标,瀑布图的精髓就是不断更新 bottom 基线!
举个简单逻辑:
- 第 0 项(期初):
bottom=0,柱子从 0 到 100 - 第 1 项(营收 + 40):
bottom=100,柱子从 100 向上加到 140 - 第 2 项(成本 + 10):
bottom=140,柱子从 140 向上加到 150 - 第 3 项(费用 - 25):
bottom=150,柱子向下到 125 - 第 4 项(税收 - 15):
bottom=125,柱子向下到 110 - 最后一项期末:
bottom=0,高度 = 110,直接画一根从 0 到 110 的总计柱
六、运行结果说明
- 蓝色:期初基数
- 绿色:正向增加
- 红色:负向扣减
- 橙色:期末汇总,直观对比期初和最终结果
七、常见坑
- 忘记计算
bottom基线:所有柱子都从 y=0 开始,变成普通柱状图,不是瀑布图 - 总计项处理错误:总计柱子不能沿用前面的 bottom,要从 0 开始画
- 负数标签位置:
va="bottom"在负数时会跑到柱子下面,可做 if 判断微调文字位置