如何为Matplotlib stackplot的重叠区域设置不同颜色
解决Matplotlib堆叠面积图负数值重叠区域着色问题
默认的stackplot会按层累加y值,当某层出现负数时,会导致当前层与下方区域重叠。要区分重叠区域,需要手动计算各层的边界,对重叠部分单独绘制:
- 第一步:计算每一层的上下基线,确定正常区域和重叠区域的分界点
- 第二步:分别绘制非重叠的正常区域,以及重叠区域(用不同颜色)
- 第三步:添加图例等元素,保证可视化清晰
以下是具体实现代码:
import matplotlib.pyplot as plt import numpy as np x = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) y2 = np.array([1, 0, -1]) # 计算第一层的基线(底层,从0到y1) base1 = np.zeros_like(x) top1 = y1 # 计算第二层的理论基线(第一层的顶部)和理论顶部(基线+y2) base2 = top1 top2 = base2 + y2 fig, ax = plt.subplots() # 先绘制第一层的完整区域 ax.fill_between(x, base1, top1, color='tab:blue', alpha=0.7, label='y1') # 处理第二层的正常区域(top2 >= base1)和重叠区域(top2 < base1) for i in range(len(x)-1): x0, x1 = x[i], x[i+1] b2_0, b2_1 = base2[i], base2[i+1] t2_0, t2_1 = top2[i], top2[i+1] # 完全无重叠的区间 if t2_0 >= base1[i] and t2_1 >= base1[i+1]: ax.fill_between([x0, x1], [b2_0, b2_1], [t2_0, t2_1], color='tab:orange', alpha=0.7) # 完全重叠的区间 elif t2_0 < base1[i] and t2_1 < base1[i+1]: # 重叠部分用特殊颜色标记 ax.fill_between([x0, x1], [t2_0, t2_1], [base1[i], base1[i+1]], color='tab:red', alpha=0.7) # 第二层正常部分保留原颜色 ax.fill_between([x0, x1], [b2_0, b2_1], [base1[i], base1[i+1]], color='tab:orange', alpha=0.7) # 区间内存在交叉点的情况 else: # 计算交叉点的x坐标 slope_t = (t2_1 - t2_0)/(x1 - x0) slope_b = (base1[i+1] - base1[i])/(x1 - x0) x_cross = x0 + (base1[i] - t2_0)/(slope_t - slope_b) # 计算交叉点对应的各边界值 t_cross = t2_0 + slope_t*(x_cross - x0) b_cross = base1[i] + slope_b*(x_cross - x0) b2_cross = b2_0 + (b2_1 - b2_0)/(x1 - x0)*(x_cross - x0) # 分两段绘制 if t2_0 >= base1[i]: # 左段非重叠,右段重叠 ax.fill_between([x0, x_cross], [b2_0, b2_cross], [t2_0, t_cross], color='tab:orange', alpha=0.7) ax.fill_between([x_cross, x1], [t_cross, t2_1], [b_cross, base1[i+1]], color='tab:red', alpha=0.7) ax.fill_between([x_cross, x1], [b2_cross, b2_1], [b_cross, base1[i+1]], color='tab:orange', alpha=0.7) else: # 左段重叠,右段非重叠 ax.fill_between([x0, x_cross], [t2_0, t_cross], [base1[i], b_cross], color='tab:red', alpha=0.7) ax.fill_between([x0, x_cross], [b2_0, b2_cross], [base1[i], b_cross], color='tab:orange', alpha=0.7) ax.fill_between([x_cross, x1], [b2_cross, b2_1], [t_cross, t2_1], color='tab:orange', alpha=0.7) # 添加图例 ax.legend(['y1', 'y2', '重叠区域']) plt.show()
代码说明:
- 先绘制底层蓝色区域,确保基础层完整展示
- 对第二层的每个区间逐一判断重叠情况,分三种场景处理:完全不重叠、完全重叠、部分重叠
- 重叠区域用红色(可自定义)标记,清晰区分负数导致的重叠部分,避免默认的区域覆盖混淆
内容的提问来源于stack exchange,提问作者at.
相关产品推荐
相关产品推荐

