如何为Python堆叠柱状图添加连接类别边缘角落的趋势线
堆叠柱状图中连接子柱状图左右角落的趋势线实现
要实现连接堆叠柱状图中每个子柱状图左右角落的趋势线,核心是获取每个主柱子的左右边界x坐标,而非中点,再对应到子柱的上下y边界。以下是修改后的完整实现:
import pandas as pd import matplotlib.pyplot as plt import numpy as np # 示例数据(包含零值测试) df = pd.DataFrame({ 'Category1': [1, 2, 0, 4], 'Category2': [2, 3, 4, 5], 'Category3': [3, 0, 5, 6] }, index=['Bar1', 'Bar2', 'Bar3', 'Bar4']) ax = df.plot(kind='bar', stacked=True) # 获取柱状图的宽度(堆叠柱的主柱子宽度统一) bar_width = ax.patches[0].width # 计算累积和,确定每个子柱状图的上边界y值 df_cumsum = df.cumsum(axis=1) # 遍历每个类别,绘制对应子柱的上下边缘趋势线 for i, category in enumerate(df.columns): # 子柱的上、下边界y值 y_upper = df_cumsum[category].values y_lower = y_upper - df[category].values # 主柱子的中点x坐标 x_mid = np.arange(len(df)) # 计算每个主柱子的左右边界x坐标 x_left = x_mid - bar_width / 2 x_right = x_mid + bar_width / 2 # 构建上边缘的点序列:依次连接每个子柱的左角落→右角落 x_upper_points = np.array([[left, right] for left, right in zip(x_left, x_right)]).flatten() y_upper_points = np.array([[y, y] for y in y_upper]).flatten() # 构建下边缘的点序列:依次连接每个子柱的左角落→右角落 x_lower_points = np.array([[left, right] for left, right in zip(x_left, x_right)]).flatten() y_lower_points = np.array([[y, y] for y in y_lower]).flatten() # 绘制趋势线,添加标记区分 plt.plot(x_upper_points, y_upper_points, marker='o', linestyle='-', label=f'{category} 上边缘') plt.plot(x_lower_points, y_lower_points, marker='s', linestyle='--', label=f'{category} 下边缘') plt.legend(loc='upper left') plt.tight_layout() plt.show()
关键修改说明
- 获取柱状图宽度:通过
ax.patches获取所有绘制的子柱子,提取第一个柱子的width属性,得到主柱子的统一宽度。 - 生成左右边界坐标:每个主柱子的中点为
np.arange(len(df)),左右边界通过中点±宽度/2计算得到。 - 构建连贯点序列:将每个柱子的左右x坐标与对应的上下y值配对展平,确保折线依次连接每个子柱的左、右角落,完全贴合子柱边缘。
- 零值兼容:当类别数值为0时,上下边界y值相等,折线会自动变为水平线段,不会出现异常显示。
内容的提问来源于stack exchange,提问作者jov14
相关产品推荐
相关产品推荐

