You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建符合需求的Matplotlib瀑布图?解决标注与布局问题

问题

使用Matplotlib创建瀑布图时遇到以下问题:

  • 数值标注位置错误
  • 末尾文本缺失
  • 缺少瀑布连接线

当前代码:

import pandas as pd
import matplotlib.pyplot as plt

data = {
    'Market': ['EU', 'EU', 'US', 'US', 'CN'],
    'Vehicle ID': ['001-1234', '001-1254', '003-7485', '001-1232', '001-2138'],
    'Status': ['Rec.', 'Rec.', 'Development', 'Stopped', 'Development']
}
df = pd.DataFrame(data)


filtered_df = df[df['Vehicle ID'].str.startswith('001')]


status_order = [
    'Wachting', 'Stopped', 'Development', 'Rec.',
]

status_counts = filtered_df['Status'].value_counts().reindex(status_order, fill_value=0)


total_count = df.shape[0]


status_counts = status_counts.append(pd.Series({'Total': total_count})).reindex(['Total'] + status_order)

plt.bar(status_counts.index, status_counts)
plt.xlabel('Status')
plt.ylabel('Number of Vehicles')
plt.title('Distribution of Vehicle Status for vehicles starting with "001"')


for index, value in enumerate(status_counts):
    plt.text(index, -0.1, str(value), ha='center')


plt.gca().axes.get_yaxis().set_visible(False)

plt.tight_layout()
plt.show()

当前图表效果:
当前图表

预期效果参考:
预期图表


解决方案

核心调整点

  1. 重构瀑布图数据逻辑:瀑布图需要展示累计变化,将Total作为起始值,后续状态用负数表示扣除量,而非直接显示原始计数
  2. 修正数值标注位置:将标注移至柱子内部/顶端,根据数值正负调整显示位置和颜色
  3. 添加瀑布连接线:通过绘制灰色虚线连接相邻柱子的顶端与底端
  4. 补全末尾文本:确保Total及所有状态的标注正常显示

完整代码

import pandas as pd
import matplotlib.pyplot as plt

data = {
    'Market': ['EU', 'EU', 'US', 'US', 'CN'],
    'Vehicle ID': ['001-1234', '001-1254', '003-7485', '001-1232', '001-2138'],
    'Status': ['Rec.', 'Rec.', 'Development', 'Stopped', 'Development']
}
df = pd.DataFrame(data)

filtered_df = df[df['Vehicle ID'].str.startswith('001')]

status_order = ['Wachting', 'Stopped', 'Development', 'Rec.']
status_counts = filtered_df['Status'].value_counts().reindex(status_order, fill_value=0)

total_count = df.shape[0]
# 构建瀑布图数据:Total为初始值,后续状态是扣除量(负数)
waterfall_data = pd.Series([total_count] + list(-status_counts.values), 
                           index=['Total'] + status_order)

# 计算累计值,确定每个柱子的底部位置
cumulative = waterfall_data.cumsum()
bottoms = [0] + list(cumulative[:-1].values)

plt.figure(figsize=(8, 5))
# 绘制瀑布柱,Total用蓝色,其余用橙色
bars = plt.bar(waterfall_data.index, waterfall_data.values, bottom=bottoms, 
               color=['#1f77b4'] + ['#ff7f0e']*len(status_order))

# 添加数值标注
for bar, val in zip(bars, waterfall_data.values):
    height = bar.get_height()
    y_pos = bar.get_y() + height / 2
    # 负数柱子用白色标注,正数用黑色
    text_color = 'white' if height < 0 else 'black'
    plt.text(bar.get_x() + bar.get_width()/2, y_pos, f'{abs(val)}', 
             ha='center', va='center', color=text_color)

# 绘制瀑布连接线
for i in range(1, len(cumulative)):
    # 连接上一柱顶端到当前柱底端
    plt.plot([i-0.5, i-0.5, i+0.5], [cumulative[i-1], cumulative[i], cumulative[i]], 
             color='gray', linestyle='--')

plt.xlabel('状态')
plt.ylabel('车辆数量')
plt.title('以"001"开头的车辆状态分布(瀑布图)')
plt.gca().axes.get_yaxis().set_visible(False)
plt.tight_layout()
plt.show()

效果说明

  • 瀑布图清晰展示从总车辆数到各状态的扣除过程
  • 数值标注位于柱子中央,可读性更强
  • 灰色虚线明确连接各阶段的数值变化
  • 配色区分起始值和扣除项,更符合预期视觉效果

内容的提问来源于stack exchange,提问作者Test

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:06:10