Python折线图如何添加重叠的fill_between上下界填充
核心结论
你设想的展开边界数据集后调用fill_between绘图的思路完全可行,且是当前场景下性价比最高的实现方案。
这不是唯一的实现方式,但其他方案本质上也需要在绘图时临时生成每个边界段对应的月度序列,和提前展开存为DataFrame的逻辑完全一致;提前展开边界表还能直接复用做指标出界校验等后续分析,不需要重复写时间匹配逻辑。
由于fill_between要求传入的x轴序列、上下界序列长度严格对齐,提前把边界映射到和指标表一致的月度粒度,能彻底避免时间错位、填充范围异常的问题,重叠区域只需要给填充色设置透明度,就能自然呈现叠加效果,不需要额外处理重叠逻辑。
具体实现步骤
- 预处理指标表:将月度指标数据按时间升序排序,避免绘图时折线顺序错乱
- 展开边界表:为每一条边界记录,生成起止日期范围内所有月初时间点(和Metric_Month的时间粒度完全对齐),再炸开为单行单月的明细结构,保留对应的上下界值
- 绘制基础图层:先画月度指标的折线+散点,作为主视觉层
- 绘制填充区域:按边界分组逐段调用
fill_between,设置低透明度保证重叠区域可见,添加图例区分不同边界组 - 调整图表格式:旋转x轴日期标签、自动适配布局,避免文字遮挡
完整可运行代码
import pandas as pd import matplotlib.pyplot as plt # ---------------------- 样例数据 ---------------------- data1 = {'Metric_Month': [pd.Timestamp('2022-05-01 00:00:00'), pd.Timestamp('2022-04-01 00:00:00'), pd.Timestamp('2022-03-01 00:00:00'), pd.Timestamp('2022-02-01 00:00:00'), pd.Timestamp('2022-01-01 00:00:00'), pd.Timestamp('2021-12-01 00:00:00'), pd.Timestamp('2021-11-01 00:00:00'), pd.Timestamp('2021-10-01 00:00:00'), pd.Timestamp('2021-09-01 00:00:00')], 'Metric_Value': [0.2876, 0.3002, 0.3169, 0.3137, 0.3022, 0.3071, 0.3122, 0.307, 0.3091]} df1 = pd.DataFrame(data1) data2 = {'start_date': [pd.Timestamp('2021-11-01 00:00:00'), pd.Timestamp('2021-10-01 00:00:00')], 'end_date': [pd.Timestamp('2022-05-01 00:00:00'), pd.Timestamp('2022-04-01 00:00:00')], 'lower_bound': [0.2954, 0.2991], 'upper_bound': [0.3221, 0.3206]} df2 = pd.DataFrame(data2) # ---------------------- 数据预处理 ---------------------- # 指标表按时间升序排序 df1 = df1.sort_values('Metric_Month').reset_index(drop=True) # 展开边界表:生成每个边界覆盖的月度序列(freq='MS'代表月初,和Metric_Month粒度对齐) df2['Metric_Month'] = df2.apply( lambda row: pd.date_range(start=row['start_date'], end=row['end_date'], freq='MS'), axis=1 ) df2_expanded = df2.explode('Metric_Month').reset_index(drop=False) # ---------------------- 绘图 ---------------------- plt.figure(figsize=(10, 6)) # 绘制指标折线+散点 plt.plot(df1['Metric_Month'], df1['Metric_Value'], color='#1f77b4', marker='o', linewidth=2, label='月度指标值') # 逐组绘制边界填充区域 for bounds_id, group in df2_expanded.groupby('index'): group = group.sort_values('Metric_Month') plt.fill_between( x=group['Metric_Month'], y1=group['lower_bound'], y2=group['upper_bound'], alpha=0.3, label=f'边界组{bounds_id+1}' ) # 图表格式调整 plt.xlabel('统计月度', fontsize=10) plt.ylabel('指标数值', fontsize=10) plt.legend() plt.xticks(rotation=45) plt.tight_layout() plt.show()
补充说明
运行代码后可以看到,两个边界重叠的2021年11月-2022年4月区间,会因为两层半透明填充叠加显示更深的颜色,视觉上可以明确区分重叠区域和非重叠区域;展开后的df2_expanded就是你预期的单月单行结构,可以直接和df1关联做指标是否超出边界的校验,不需要再重复做时间匹配。
内容的提问来源于stack exchange,提问作者Lior
相关产品推荐
相关产品推荐

