You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Matplotlib:绘制Datetime轴时如何跳过指定时段?

解决Matplotlib绘制多交易日Tick数据时跳过非交易时段的问题

嘿,我之前也碰到过一模一样的麻烦!用Matplotlib画跨交易日的逐笔数据时,收盘到次日开盘的空白时段总让图表显得松散,价格线还断得特别别扭,直接调plt.xticks根本解决不了对吧?别慌,咱们换个思路就能搞定——把时间轴换成连续的数值索引,再手动把时间标签贴回去,这样就能完美跳过非交易时段,让收盘价和次日开盘价无缝衔接。

核心思路

Matplotlib默认会按DatetimeIndex的实际时间间隔绘图,非交易时段的时间差自然会留出空隙。我们用连续的整数作为x轴坐标,让每个tick数据点紧密排列,再把对应的时间标签映射到这些整数位置上,既保证了图表的连续性,又能正确展示时间信息。

完整实现代码

直接把下面的代码替换你原来的绘图部分就行,我已经适配了你的示例数据:

import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt

# 示例数据
instrument = pd.DataFrame(data={
 'Datetime': [
 dt.datetime.strptime('2018-01-11 11:00:11', '%Y-%m-%d %H:%M:%S'),
 dt.datetime.strptime('2018-01-11 13:02:17', '%Y-%m-%d %H:%M:%S'),
 dt.datetime.strptime('2018-01-11 16:59:14', '%Y-%m-%d %H:%M:%S'),
 dt.datetime.strptime('2018-01-12 11:00:11', '%Y-%m-%d %H:%M:%S'),
 dt.datetime.strptime('2018-01-12 13:15:24', '%Y-%m-%d %H:%M:%S'),
 dt.datetime.strptime('2018-01-12 16:58:43', '%Y-%m-%d %H:%M:%S')
 ],
 'Price': [127.6, 128.1, 127.95, 129.85, 129.7, 131.2],
 'Volume': [725, 146, 48, 650, 75, 160]
}).set_index('Datetime')

# 给每个tick添加连续的数值索引
instrument['x'] = range(len(instrument))

plt.figure(figsize=(10,5))
top = plt.subplot2grid((4,4), (0, 0), rowspan=3, colspan=4)
bottom = plt.subplot2grid((4,4), (3,0), rowspan=1, colspan=4)

# 用数值索引x代替DatetimeIndex绘图
top.plot(instrument['x'], instrument['Price'])
# 调整柱状图宽度,适配数值索引的间隔
bottom.bar(instrument['x'], instrument['Volume'], width=0.3)

# 隐藏顶部子图的x轴
top.axes.get_xaxis().set_visible(False)
top.set_title('Example (No Gaps Between Trading Days)')
top.set_ylabel('Price')
bottom.set_ylabel('Volume')

# 自定义底部子图的x轴标签,显示关键时间点
# 按日期分组,提取每天的开盘和收盘时间作为标签
tick_positions = []
tick_labels = []
grouped = instrument.groupby(instrument.index.date)

for date, group in grouped:
    # 添加当天第一个和最后一个tick的x位置
    tick_positions.append(group['x'].iloc[0])
    tick_positions.append(group['x'].iloc[-1])
    # 格式化时间标签,你可以根据需求调整格式
    tick_labels.append(group.index.iloc[0].strftime('%Y-%m-%d\n%H:%M'))
    tick_labels.append(group.index.iloc[-1].strftime('%Y-%m-%d\n%H:%M'))

# 设置x轴刻度和标签
bottom.set_xticks(tick_positions)
bottom.set_xticklabels(tick_labels, rotation=0, ha='center')

plt.tight_layout()
plt.show()

额外优化:区分不同交易日

如果想让不同交易日的图表之间有一点点小空隙(方便区分日期),可以修改数值索引的生成逻辑,给每个交易日加个偏移量:

offset = 0.5  # 交易日之间的间隔大小
current_offset = 0
instrument['x'] = 0

grouped = instrument.groupby(instrument.index.date)
for date, group in grouped:
    # 给当前交易日的x值加上偏移
    instrument.loc[group.index, 'x'] = range(current_offset, current_offset + len(group))
    current_offset += len(group) + offset

这样绘图后,不同交易日之间会有一个微小的空隙,既不影响整体连续性,又能清晰区分日期。

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

火山引擎 最新活动