0

当前的项目是绘制一系列时间框架,这些时间框架都标准化为相同的,即使发生在一年中的不同时间,每年。

每个时间周期都有一个定义的开始和结束,参考周期内的事件来说明。在这种情况下,公司在一年中的某些时间报告收益。每个报告周期中的共同事件是公司在何时向公众公布财务报告时发出通知。

分配公告被视为“第 0 天”,周期内的所有其他事件均相对于公告日期绘制图表。它们发生在公告日期之前或之后的“x”天。

Matplotlib 将使用正在绘制的数据中的最小值/最大值自动设置范围。我正在尝试将 x 股票代码设置为 5,以 Announcement Date (0) 为基础

如果我使用:

ax.xaxis.set_major_locator(plt.IndexLocator(base=5, offset=0))

它在循环中不使用“第 0 天”,而是使用 x 轴上的第一个 (0) 位置作为偏移量,然后将下一个代码放在 5 处。

因此,如果我的数据集中周期的最短开始时间是在公告日期前 53 天(我的“0”),那么它会在 -53 处绘制第一个 x-ticker,在 -48、-43 处绘制下一个.它不以我的'0'为中心。但最小的 x 值。

但是,如果我使用以下方法在“0”处画一条垂直线:

ax.vlines(0,-1,len(df))

它将它绘制在正确的位置,但该行与“0”代码匹配的唯一方法是当第一个代码是 5 的倍数时。

(在我的示例数据集中,xmin = -53,在 -3 和 2 代码之间画了一条线。

如何强制定位器在我的“0”所在的图表中间偏移?

或者,我可以强制第一个代码自动将自己粘到最接近的 5 倍数上吗?

4

1 回答 1

0

与其说是对我的问题的回答,不如说是对我的问题的解决方案。事实证明,使用 IndexLocator 作为设置 x 轴 major_locator 的基础并不是我想要的。

我应该使用 MultipleLocator 代替。

这是完成我想要的完整代码:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator)

def round_to_five( n ): # function to round the number to the nearest 5

    # Smaller multiple
    a = (n // 5) * 5
 
    # Larger multiple
    b = a + 5
 
    # Return of closest of two
    return (b if n - a > b - n else a)


data = {'Period':['Q1','Q2','Q3','Q4'], 'Start':[-3,-18,-21,-29], 'End':[21,37,48,12]}

df = pd.DataFrame(data)

graph_start = round_to_five(df['Start'].min())  # set the left boundary to the nearest multiple of 5
graph_end = round_to_five(df['End'].max()) # set right boundary to the nearest multiple of 5

fig, ax = plt.subplots()

ax.vlines(0,-1,len(df['Period']),color='green', linewidth = 2, zorder = 0, label='Announcement' )      # show event reference line at Day 0.

ax.scatter(df['Start'],df['Period'],color = 'purple', label = 'Cycle Start', marker = '|', s = 100, zorder = 2)  # plot cycle start in number of days before Announcement Date.
ax.scatter(df['End'],df['Period'],color = 'red', label = 'Cycle End', marker = '|', s = 100, zorder = 2)    # plot cycle end in number of days after Announcement Date.

ax.hlines(df['Period'], xmin=df['Start'], xmax=df['End'], color='blue', linewidth = 1, zorder = 1)  # show cycle

ax.legend(ncol=1, loc = 'upper right')

## Set min and max x values as left and right boundaries, and then makes ticks to be 5 apart.
ax.set_xlim([graph_start-5, graph_end+5]) 
ax.xaxis.set_major_locator(MultipleLocator(5))

ax.tick_params(axis = 'x', labelrotation = 60)

plt.show()
于 2021-02-27T09:50:12.487 回答