python - 如何构建自定义 pandas.tseries.offsets 类?

标签 python pandas matplotlib datetimeoffset

我想找到一种方法,在交易时间内以 1 秒的频率构建自定义 pandas.tseries.offsets 类。这里的主要要求是时间偏移对象足够聪明,可以知道“2015-06-18 16:00:00”的下一秒是“2015-06-19 09:30:00 或 09:30”: 01',并且根据这两个时间戳计算的时间增量将恰好为 1s(自定义偏移量 1s,类似于工作日频率的 BDay(1))而不是关闭时间的持续时间。

原因是在绘制 pd.Series 的几个交易日的盘中数据时,请参见下面的模拟示例,收盘价和次日开盘价之间有很多“步进线”(线性插值)来表示关闭时间的持续时间。有没有办法摆脱这个?我查看了 pandas.tseries.offsets 的源代码并找到了 pd.tseries.offsets.BusinessHourpd.tseries.offsets.BusinessMixin 可能有帮助,但我不知道如何使用它们。

import pandas as pd
import numpy as np
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay

# set as 'constant' object shared by all codes in this script
BDAY_US = CustomBusinessDay(calender=USFederalHolidayCalendar())
sample_freq = '5min'
dates = pd.date_range(start='2015-01-01', end='2015-01-31', freq=BDAY_US).date
# exculde the 09:30:00 as it is included in the first time bucket
times = pd.date_range(start='09:30:00', end='16:00:00', freq=sample_freq).time[1:]
time_stamps = [dt.datetime.combine(date, time) for date in dates for time in times]
s = pd.Series(np.random.randn(len(time_stamps)).cumsum() + 100, index=time_stamps)

s.plot()

enter image description here

另一种我能想到的部分解决这个问题的方法是先reset_index()获取每一行的默认连续整数索引,然后计算连续整数索引之间的差作为时间(以秒为单位)过去了。将整数索引绘制为 x 轴,然后将它们重新标记为适当的时间标签。有人可以告诉我如何使用 matplotlib 来做吗?

感谢杰夫的评论。我只是检查了 BusinessHour() 的联机文档,发现它对我的情况可能很有用。另一个后续问题: BusinessHour 是小时频率,有没有办法让它成为 1s 频率?另外,如何将它与 CustomBusinessDay 对象结合起来?

使用 BusinessHour()

from pandas.tseries.offsets import *
bhour = BusinessHour(start='09:30', end='16:00')
time = pd.Timestamp('2015-06-18 15:00:00')
print(time)
2015-06-18 15:00:00
# hourly increment works nicely
print(time + bhour * 1)
2015-06-19 09:30:00
# but not at minute or second frequency
print(time + Minute(61))
2015-06-18 16:01:00
print(time + Second(60*60 + 1))
2015-06-18 16:00:01

非常感谢,如有任何帮助,我们将不胜感激。

最佳答案

正如我在评论中提到的,您可能有两个不同的问题

  1. 您需要能够在没有长线性插值的情况下绘制仅业务时间的时间序列。
  2. 您需要一个可以忽略非业务时间的日期时间算术(以秒为单位)的对象

我给出了一个占 1 的解决方案,因为这似乎是您的直接问题。如果您需要 2 个,或两者都需要 - 请在评论中告诉我们:

1。绘制与工作日相邻的点

matplotlib 中的大多数图表都可以通过 ticker API 将索引格式化程序应用于轴。 .我会适应 this example适合你的情况

import pandas as pd
import numpy as np
from pandas.tseries.holiday import USFederalHolidayCalendar
from pandas.tseries.offsets import CustomBusinessDay
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

# set as 'constant' object shared by all codes in this script
BDAY_US = CustomBusinessDay(calender=USFederalHolidayCalendar())
sample_freq = '5min'
dates = pd.date_range(start='2015-01-01', end='2015-01-31', freq=BDAY_US).date
# exculde the 09:30:00 as it is included in the first time bucket
times = pd.date_range(start='09:30:00', end='16:00:00', freq=sample_freq).time[1:]
time_stamps = [dt.datetime.combine(date, time) for date in dates for time in times]
s = pd.Series(np.random.randn(len(time_stamps)).cumsum() + 100, index=time_stamps)

data_length = len(s)
s.index.name = 'date_time_index'
s.name='stock_price'
s_new = s.reset_index()

ax = s_new.plot(y='stock_price') #plot the data against the new linearised index...

def format_date(x,pos=None):
    thisind = np.clip(int(x+0.5), 0, data_length-1)
    return s_new.date_time_index[thisind].strftime('%Y-%m-%d %H:%M:%S')

ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))

fig = plt.gcf()
fig.autofmt_xdate()

plt.show()

这给出了如下输出,首先以自然比例缩小,然后放大,以便您可以看到周五 16:00 和周一 09:00 之间的过渡

zoomed out time series

zoomed in time series over a weekend

关于python - 如何构建自定义 pandas.tseries.offsets 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30946968/

相关文章:

python - 如何将第 3 方 Python 库导入 Bluemix?

python - 如何迭代文件夹中的文件以移动具有特定扩展名的每个文件

python - 带有 stub 列表的 Pandas Wide_to_long

python - 替换另一列中的缺失值 - pandas

Python matplotlib开罗错误

python - 如何在 tensorboard 中显示 Tensorflow 2.0 中的 tf.data.Dataset.map 子图?

python - 如何在 Scikit-learn 中获取 OneHotEncoder 的维度数

一组中的 Python Pandas 最大值作为新列

python - 在 Matplotlib 中以绝对方式(而非相对)调整一个子图的高度

python - 具有多处理卡住计算机的 Matplotlib