【问题标题】:How to add hours to pandas datetime skipping non-business hours如何跳过非营业时间向熊猫日期时间添加小时数
【发布时间】:2019-08-21 18:07:18
【问题描述】:

我想在跳过非交易时间(工作日下午 5 点至下午 6 点,周六至周日下午 6 点)的同时创建一个从当前时间开始的接下来四个小时的交易数据的运行数据框。例如,周五下午 4 点,我想要一个从周五下午 4 点到下午 5 点,然后在周日下午 6 点到 9 点运行的数据框。

目前,我正在使用以下内容:

time_parameter = pd.Timedelta(hours=4) #Set time difference to four hours
df = df.set_index(['Time']) 

for current_time, row in df.iterrows(): #df is the entire trading data df
    future_time = current_time + time_parameter
    temp_df = df.loc[current_time : future_time]

这显然不会跳过非交易时间,所以我试图找到一种有效的方法来做到这一点。

我可以使用的一种方法是创建一组非交易时间,检查当前时间范围 (current_time:future_time) 是否包括任何时间,并为每个时间添加额外的时间。

但是,由于数据集大约有 350 万行,并且需要对每一行进行此检查,我想问是否有人知道更快的方法?

简而言之,寻找一种将 4 个工作时间(周日至周五下午 6 点至下午 5 点)添加到当前时间的方法。谢谢!

Input Data: This shows the first 19 rows of the trading data

Expected Output Data: This shows the first and last 3 rows from a four hour period starting at 18:00:30 on January 8th, 2017


解决方案

根据下面代码不同的答案,我使用了以下内容:

def last_trading_hour(start_time, time_parameter, periods_parameter):
    start_series = pd.date_range(start_time, freq='H', periods = periods_parameter)
    mask = (((start_series.dayofweek == 6) & (time_2(18) <= start_series.time)) #Sunday: After 6pm
    | ((start_series.dayofweek == 4) & (start_series.time < time_2(17))) #Friday before 5pm
    | ((start_series.dayofweek < 4) & (start_series.time < time_2(17))) #Mon-Thur before 5pm
    | ((start_series.dayofweek < 4) & (time_2(18) <= start_series.time)) #Mon-Thur after 6pm
    )

    return start_series[mask][time_parameter]

start_time = pd.Timestamp('2019-08-16 13:00:10')
time_parameter = 4 #Adding 4 hours to time
periods_parameter = 49 + time_parameter #Max 49 straight hours of no-trades (Fri 5pm-Sun 6pm)
last_trading_hour(start_time, time_parameter, periods_parameter)

结果:

Timestamp('2019-08-18 18:00:10')

如果你需要整个系列,请按照 Code Different 的方法进行索引。

【问题讨论】:

  • 欢迎来到 StackOverflow。请按照您创建此帐户时的建议遵循帮助文档中的发布指南。 On topichow to ask 和 ...the perfect question 在此处申请。 StackOverflow 不是设计、编码、研究或教程资源。向我们展示您的输入、输出和编码尝试?

标签: python pandas timedelta


【解决方案1】:

生成足够长的时间序列,然后过滤前 4 个交易时间:

from datetime import time

start_time = pd.Timestamp('2019-08-16 16:00')
s = pd.date_range(start_time, freq='H', periods=72)

is_trading_hour = (
    ((s.weekday == 6) & (time(18) <= s.time))
    | ((s.weekday == 4) & (s.time < time(17)))
    | (s.weekday < 4)
)

s[is_trading_hour][:4]

结果:

DatetimeIndex(['2019-08-16 16:00:00', '2019-08-18 18:00:00',
               '2019-08-18 19:00:00', '2019-08-18 20:00:00'],
              dtype='datetime64[ns]', freq=None)

【讨论】:

  • 谢谢!这很有帮助。为了我的特定目的,我对其进行了一些修改,并在上面添加了这一点,以防其他人有类似的问题。
【解决方案2】:

很难从这么少的信息中分辨出来。但是,您似乎正在处理时间限制。如果是这样,那么设置一个以每天和每小时为关键字的查找表 (dict) 应该很简单,也许:(0,0) 表示周日/周一午夜,(2, 13) 表示周三下午 1 点,等等。然后提供 4 小时结束时的简单条目

(0, 0): Timedelta(hours= 4),    #  0:00 Mon, normal span; regular trading hours
(0,16): Timedelta(hours= 5),    # 16:00 Sun; 1 hour of down-time
(4,16): Timedelta(hours=53),    # 16:00 Fri; 1 hour trade, 49 hrs down, 3 hrs trade
(5,16): Timedelta(hours=26),    # 16:00 Sat; 26 hours down, 4 hours trade

将指示的Timedelta 添加到您的开始时间;这为您提供了该期间的结束时间。您可以编写几个循环和if 语句来为您计算这些时间,或者只是硬编码所有 168;它们相当重复。

检查您的数据库行仍然取决于您,因为您没有在您的帖子中指定它们的格式或语义。

【讨论】:

  • 嘿!感谢您的答复。在我的帖子中包含哪些有用的附加信息?
  • 请参阅我对该问题的评论中的一般说明,以及我在此答案中传递的数据的详细信息。
猜你喜欢
  • 2020-02-07
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 2016-07-05
  • 2020-05-18
  • 2020-08-11
  • 1970-01-01
  • 2020-11-18
相关资源
最近更新 更多