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

Matplotlib柱状图分段阈值水平线绘制问题求助

问题需求

我需要在柱状图中创建3条阈值水平线,每条线仅延伸至对应Tenor的日期范围,到下一个Tenor时换线接续。数据包含Cash、End Date、Tenor三列。现有代码无法实现分段显示,水平线会贯穿整个图表宽度;尝试修改axhline的xmin/xmax参数但无效,同时需要在每个Tenor结束位置绘制垂直线分隔。

当前效果:水平线贯穿全图,无分段
预期效果:水平线按Tenor分段显示,Tenor结束处有垂直线分隔


现有代码
import pandas as pd
import matplotlib.pyplot as plt


df = {'Cash':[900e6,800e6,700e6,600e6,500e6,400e6,300e6,200e6,100e6,0],
      'End Date': ['27/03/2023','28/03/2023','29/03/2023','30/03/2023','31/03/2023','01/04/2023','02/04/2023','20/09/2023','21/09/2023','21/01/2024'],
      'Tenor': ['1-3 Month','1-3 Month','1-3 Month','1-3 Month','1-3 Month','1-3 Month','1-3 Month','6 Month','6 Month','9Month']}
df = pd.DataFrame(data = df)
pd.to_datetime(df['End Date'])


fig, ax = plt.subplots(figsize=(10, 100))
for tenor, group in df.groupby('Tenor'):
    cash_out_limits = [200e6, 300e6, 500e6] # define cash out limits for each tenor
    last_end_date = group.iloc[-1]['End Date'] # get the last end date for each tenor
    start_end_date = group.iloc[0]['End Date']
    print(start_end_date)
    # create a red hline for each cash out limit
    for limit in cash_out_limits:
        ax.axhline(limit, color='r', linestyle='--')

    
# plot cash out vs end date as a bar chart
df.plot(x='End Date', y='Cash', kind='bar', ax=ax)

plt.show()

尝试过的无效代码
for limit in cash_out_limits:  
    ax.axhline(y=limit, xmin = start_end_date, xmax = last_end_date, color='r', linestyle='--')

解决方案

问题核心是axhline的xmin/xmax需要的是坐标轴相对位置(0到1之间),而非日期字符串。另外柱状图的x轴是分类轴,每个柱子对应一个索引位置,需通过分组的索引范围确定水平线起止,同时绘制垂直线分隔Tenor。

修改后的完整代码:

import pandas as pd
import matplotlib.pyplot as plt

# 数据处理:正确解析日期并保留原始索引
df = {
    'Cash': [900e6,800e6,700e6,600e6,500e6,400e6,300e6,200e6,100e6,0],
    'End Date': ['27/03/2023','28/03/2023','29/03/2023','30/03/2023','31/03/2023','01/04/2023','02/04/2023','20/09/2023','21/09/2023','21/01/2024'],
    'Tenor': ['1-3 Month','1-3 Month','1-3 Month','1-3 Month','1-3 Month','1-3 Month','1-3 Month','6 Month','6 Month','9Month']
}
df = pd.DataFrame(data=df)
df['End Date'] = pd.to_datetime(df['End Date'], dayfirst=True)

fig, ax = plt.subplots(figsize=(12, 6))

# 先绘制柱状图,确保x轴索引对应正确
df.plot(x='End Date', y='Cash', kind='bar', ax=ax)

cash_out_limits = [200e6, 300e6, 500e6]
total_bars = len(df)

# 遍历每个Tenor分组,绘制分段水平线和垂直线
for tenor, group in df.groupby('Tenor'):
    start_idx = group.index[0]
    end_idx = group.index[-1]
    
    # 将柱子索引转换为axhline需要的相对坐标(0-1范围)
    xmin = (start_idx - 0.5) / (total_bars - 1) if total_bars > 1 else 0
    xmax = (end_idx + 0.5) / (total_bars - 1) if total_bars > 1 else 1
    
    # 绘制分段阈值水平线
    for limit in cash_out_limits:
        ax.axhline(y=limit, xmin=xmin, xmax=xmax, color='r', linestyle='--')
    
    # 绘制Tenor分隔垂直线(最后一个分组不画)
    if end_idx != total_bars - 1:
        ax.axvline(x=end_idx + 0.5, color='gray', linestyle='-')

# 优化图表显示
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

关键修改说明:

  1. 正确解析日期格式,避免索引混乱
  2. 利用分组的原始索引计算柱状图的x轴位置,转换为axhline所需的相对坐标
  3. 垂直线绘制在分组最后一个柱子的右侧(end_idx + 0.5位置)
  4. 调整图表尺寸和标签角度,提升可读性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:52:07