Python Pandas,仅对特定小时进行重新采样。

5

我的pandas版本是0.18,我有一个类似下面的分钟数据:

Time                              
2009-01-30 09:30:00  85.11  100.11
2009-01-30 09:39:00  84.93  100.05
2009-01-30 09:40:00  84.90  100.00
2009-01-30 09:45:00  84.91   99.94
2009-01-30 09:48:00  84.81   99.90
2009-01-30 09:55:00  84.78  100.00
2009-01-30 09:56:00  84.57  100.10
2009-01-30 09:59:00  84.25  100.41
2009-01-30 10:00:00  84.32  100.60
2009-01-30 10:06:00  84.23  101.49
2009-01-30 10:09:00  84.15  101.47

我希望仅使用9:30和16:00之间的数据,并将数据重新采样为78分钟间隔(即将9:30和16:00之间的时间分为5个等份)。我的代码如下:

Data= Data.between_time('9:30','16:00')
tframe = '78T'
hourlym = Data.resample(tframe, base=30).mean()

输出结果:

Time                                      
2009-01-30 08:18:00  85.110000  100.110000
2009-01-30 09:36:00  83.950645  101.984516
2009-01-30 10:54:00  83.372294  103.093824
2009-01-30 12:12:00  83.698624  102.566897
2009-01-30 13:30:00  83.224397  103.076667
2009-01-30 14:48:00  82.641167  104.114667
2009-01-30 16:06:00        NaN         NaN
2009-01-30 17:24:00        NaN         NaN
2009-01-30 18:42:00        NaN         NaN

如您所见,Pandas忽略了我的基准参数,而且我的输出表从 8:18 开始。我相信这是因为Pandas试图将数据正确地分成每 78 分钟一组,由于 24 小时无法平均分配到 78 分钟,所以会出现这种奇怪的行为。是否可以强制Pandas从第一天的9:30开始重新采样?或者只在重新采样时使用特定的小时数?


可能是打错了吗?你输入的是 tframe = '78T' 而不是 72 分钟。 - IanS
很遗憾不是的 :( 实际上78分钟才是正确的数字,所以我在描述中打错了。 - kroonike
2个回答

5
base参数应用于午夜,因此在您的情况下,采样从00:30开始,并从那里每次增加78分钟。我看到有两个选项。 选项1
找出午夜时应该应用什么base才能达到9:30(在这种情况下为24):
Data.resample(tframe, base=24)

选项2:

自己生成datetimeindex,然后使用reindex进行重新采样:

index = pd.date_range('2009-01-30 09:30:00', '2009-01-30 16:00:00', freq='78min')
Data.reindex(index=index)

编辑:如果需要多天的时间戳,您需要自己生成。

index_date = pd.date_range('2016-04-01', '2016-04-04')
index_date = pd.Series(index_date)
index_time = pd.date_range('09:30:00', '16:00:00', freq='78min')
index_time = pd.Series(index_time.time)

index = index_date.apply(
    lambda d: index_time.apply(
        lambda t: datetime.combine(d, t)
        )
    ).unstack().sort_values().reset_index(drop=True)

这段代码的作用如下:
  • 生成你感兴趣的日期和时间,并将它们变成系列以便具有apply属性。
  • 使用嵌套的“apply”循环遍历日期和时间,并将它们组合成一个日期时间对象。
  • 输出是一个方形数据框(每个日期一列),因此我使用了“unstack”来排序时间戳(最后重置索引以摆脱途中生成的无用索引)。

结果的index可以像最初的Option 2那样用于重新索引:

Data.reindex(index=index)

这两个选项的问题在于,24小时无法被78分钟等分,因此我的数据在第一天后开始偏移(但可以将9:30到16:00的数据分成78分钟的块)。我希望我的数据每天有完全相同的5个时间索引,并忽略16:00和9:30之外的时间。 - kroonike
好的,多天,明白了。 - IanS
是的,代码可行!我想知道现在是否可以使用自定义函数和新索引重新采样我的初始数据?此外,如果您能简要解释一下代码背后的逻辑,我将非常感激。 - kroonike
我会添加解释。你指的是哪个自定义函数? - IanS
1
我稍微修改了代码,以便更容易解释。请检查一下。 - IanS

2

IanS给出的答案非常完整。

我注意到你的问题中涉及到的日期,我认为你正在尝试在印度交易情境下进行这些操作。因此,最好使用pd.tseries.offsets.CustomBusinessDay(holidays=holiday_list)创建自定义日历:https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html?highlight=holiday#custom-business-days

例如,从1980-2025(仅限工作日)+删除1980-2025年的交易假日列表(可以搜索谷歌获取该信息)。

如果您正在进行纸上交易回测并从多个股票导入数据,则可以使用此方法。


或者您可以安装package包:pip install pandas_market_calendars

import pandas_market_calendars as mcal

# Create a calendar
nyse = mcal.get_calendar('NYSE')

# Show available calendars
print(mcal.get_calendar_names())

early = nyse.schedule(start_date='2012-07-01', end_date='2012-07-10')
early

                  market_open             market_close
=========== ========================= =========================
 2012-07-02 2012-07-02 13:30:00+00:00 2012-07-02 20:00:00+00:00
 2012-07-03 2012-07-03 13:30:00+00:00 2012-07-03 17:00:00+00:00
 2012-07-05 2012-07-05 13:30:00+00:00 2012-07-05 20:00:00+00:00

mcal.date_range(early, frequency='1D')

DatetimeIndex(['2012-07-02 20:00:00+00:00', '2012-07-03 17:00:00+00:00',
               '2012-07-05 20:00:00+00:00', '2012-07-06 20:00:00+00:00',
               '2012-07-09 20:00:00+00:00', '2012-07-10 20:00:00+00:00'],
              dtype='datetime64[ns, UTC]', freq=None)

mcal.date_range(early, frequency='1H')

DatetimeIndex(['2012-07-02 14:30:00+00:00', '2012-07-02 15:30:00+00:00',
               '2012-07-02 16:30:00+00:00', '2012-07-02 17:30:00+00:00',
               '2012-07-02 18:30:00+00:00', '2012-07-02 19:30:00+00:00',
               '2012-07-02 20:00:00+00:00', '2012-07-03 14:30:00+00:00',

然后只需执行

Data.reindex(index=name_of_date_object_list)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接