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

Python时间轴优化:调整日期线与事件文本的间距

解决Matplotlib时间轴的两个布局问题

原实现代码与效果

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

df = pd.DataFrame(
    {
        'event': ['Qfpgv KFJPF fpnkmkq',
                  'Ltzx cqwup xnywi bxfjzgq ol mwwqmg ukszs',
                  'MUTD ysrfzad Urmiv lqyjexdq xqkqzfx vqtwrgh',
                  'Vxdys vjxqnqojq qvqoshjmhv dmyzf fj wvtrjv',
                  'Kcxtm-Bix Nzvlqj ajmydgbxk',
                  'Nrsbo! ukguvle xavahfg tqyikwqg, UZSP tgrlqfr',
                  'Rjxetf/uzpqwhwr qtshxvlp tljybtncbq qvqybnjgq dzqj',
                  'Qwvbt-Khspqw olfypkbvh tljmyyvz ajmy zazvqfm',
                  'UHW Umkqtqm zvhq tljybtncbq',
                  'Wwscye rukqdf, vfyvqmf udzvqmcv tljybtncbq',
                  'Twljq uqtrjxwh hyvnvwbl tljmyyvz rbykqkwqjg djzv Kqkmv xnyzqmv.',
                  'Qfpgv Qnwroj rymqzqm tljybtncbq kxqj vq Kqmnjp kxqkz.',
                  'Vwkqr jvqjg fqtwp, Jvccjvj CQM Sgqhojif mblqjc',
                  'Qxltj dqg Vqsue tljmyyvz jvtsqjwuj wkhruwqlqj, ixdro xqjolvkphw',
                  'Rwkq Vqwdqlqj odujhg jvswhuh fduuleolqj',
                  'Nzvq nqfupxqj jtsqjwuj',
                  'Vqolqjyphfwhv sohwwhuqvhtg jtsqjwuj',
                  'Ulnwj ri gihw dqg rqooih OY wlg ihghovdfh orqjv',
                  'Fkxohqjdoahoo sohwwhu ydplqhuv rqh wkhhtxdo jtsqjwuj'
                 ],
        'date': ['1984', '1987', '1991', '1994', '1997', '1998', '1999', '2002', '2004',
                 '2005', '2007', '2009', '2010', '2012', '2013', '2014', '2017', '2019', '2021']
    }
)

df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].dt.year

levels = np.tile(
    [-5, 5, -3, 3, -1, 1, -7, 7, -4, 4, -2, 2, -6, 6, -3, 3, -1, 1, -5, 5, -3, 3, -1, 1, 5],
    int(np.ceil(len(df) / 6))
)[:len(df)]

fig, ax = plt.subplots(figsize=(12.8, 4), constrained_layout=True)

ax.vlines(df['date'], 0, levels, color="tab:red")  # The vertical stems.
ax.plot(  # Baseline and markers on it.
    df['date'],
    np.zeros_like(df['date']),
    "-o",
    color="k",
    markerfacecolor="w"
)

# annotate lines
for d, l, r in zip(df['date'], levels, df['event']):
    lines = r.split(' ')
    line1 = ' '.join(lines[:len(lines)//2])
    line2 = ' '.join(lines[len(lines)//2:])
    ax.annotate(
        line1 + '\n' + line2,
        xy=(d, l),
        xytext=(-5, np.sign(l) * 15),  # Increase the y-offset for more vertical space
        textcoords="offset points",
        horizontalalignment="center",
        verticalalignment="bottom",
        fontsize=8  # Adjust the font size to fit the annotations within the plot
    )
    
ax.text(0.5, 1.3, "PLOT PLOT PLOT", transform=ax.transAxes,  
         fontsize=16, fontweight='bold', ha='center') 
ax.get_yaxis().set_visible(False)  # Remove the y-axis
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)

plt.show()

时间轴效果


问题1:日期基线与下方事件名称重叠

解决方案:
通过区分正负事件的垂直对齐方式,并调整偏移量,拉开下方事件与基线的距离:

  1. 对负向事件(levels为负)设置垂直对齐为top,让文字底部紧贴茎线端点;
  2. 给负向事件设置向下的偏移量,进一步远离基线;
  3. 可选:调整levels数组的负向数值,加长下方茎线的长度,从根源上增加间距。

修改后的注释代码片段:

# annotate lines
for d, l, r in zip(df['date'], levels, df['event']):
    lines = r.split(' ')
    line1 = ' '.join(lines[:len(lines)//2])
    line2 = ' '.join(lines[len(lines)//2:])
    
    # 根据事件位置设置不同的对齐和偏移
    if l < 0:
        va = 'top'
        y_offset = -18  # 向下偏移,拉开与基线的距离
    else:
        va = 'bottom'
        y_offset = 15
    
    ax.annotate(
        line1 + '\n' + line2,
        xy=(d, l),
        xytext=(0, y_offset),  # 取消x方向偏移,避免文字错位
        textcoords="offset points",
        horizontalalignment="center",
        verticalalignment=va,
        fontsize=8
    )

可选调整levels数组:

levels = np.tile(
    [-6,6,-4,4,-2,2],  # 加大负向数值的绝对值,加长下方茎线
    int(np.ceil(len(df) / 6))
)[:len(df)]

问题2:正向事件与水平基线存在间距

解决方案:
上述修改已同时解决此问题:对正向事件(levels为正)设置垂直对齐为bottom,让文字顶部紧贴茎线的顶端,从而消除与基线的间距,和负向事件保持一致的紧贴效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:15:56