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




