【问题标题】:Extract Business Days in Time Series using Python/Pandas使用 Python/Pandas 提取时间序列中的工作日
【发布时间】:2014-10-25 04:08:48
【问题描述】:

我正在处理时间序列中的高频数据,我想从我的数据中获取所有工作日。我的数据观察以秒为单位,所以每天有 86400 秒,我的数据集分布在 31 天(所以有 2,678,400 个观察!)。

这是我的(部分)数据:

In[1]: ts
Out[1]: 
2013-01-01 00:00:00    0.480928
2013-01-01 00:00:01    0.480928
2013-01-01 00:00:02    0.483977
2013-01-01 00:00:03    0.486725
2013-01-01 00:00:04    0.486725
...
2013-01-31 23:59:56    0.451630
2013-01-31 23:59:57    0.451630
2013-01-31 23:59:58    0.451630
2013-01-31 23:59:59    0.454683
Freq: S, Length: 2678400

我想做的是创建一个新的时间序列,其中包含本月的工作日,但我希望它们具有相应的数据秒数。 例如,如果 2013 年 1 月 2 日(星期三)到 2013 年 1 月 4 日(星期五)是 1 月第一周的第一个工作日,那么:

2013-01-02 00:00:00    0.507477
2013-01-02 00:00:01    0.501373
...
2013-01-03 00:00:00    0.489778
2013-01-03 00:00:01    0.489778
...
2013-01-04 23:59:58    0.598115
2013-01-04 23:59:59    0.598115
Freq: S, Length: 259200

所以它当然会排除 2013 年 1 月 5 日和 2013 年 1 月 6 日星期六的所有数据,因为这些是周末。 等等……

我尝试使用一些 pandas 内置命令,但找不到合适的命令,因为它们按天聚合,而没有考虑到每一天都包含子列。也就是说,每一秒都有一个值,它们不应该被平均,只是组合在一起形成一个新的系列..

例如我试过:

  1. ts.asfreq(BDay()) --> 找到工作日,但每天的平均值
  2. ts.resample() --> 你必须定义“如何”(平均值、最大值、最小值...)
  3. ts.groupby(lambda x : x.weekday) --> 也不是!
  4. ts = pd.Series(df, index = pd.bdate_range(start = '2013/01/01 00:00:00', end = '2013/01/31 23:59:59' , freq = 'S')) --> df 因为原始数据是 DataFramem。 使用 pd.bdate_range 并没有帮助,因为 df 和 index 必须在同一维度中..

我在 pandas 文档中搜索,谷歌搜索但找不到线索...
有人有想法吗?

非常感谢您的帮助!

谢谢!

附言 我宁愿不使用循环,因为我的数据集非常大...... (我还有其他月份要分析)

【问题讨论】:

    标签: python pandas time-series


    【解决方案1】:

    不幸的是,这有点慢,但至少应该给出您正在寻找的答案。

    #create an index of just the date portion of your index (this is the slow step)
    ts_days = pd.to_datetime(ts.index.date)
    
    #create a range of business days over that period
    bdays = pd.bdate_range(start=ts.index[0].date(), end=ts.index[-1].date())
    
    #Filter the series to just those days contained in the business day range.
    ts = ts[ts_days.isin(bdays)]
    

    【讨论】:

    • 这正是我想要的。工作完美!谢谢!
    【解决方案2】:

    现代pandas 将时间戳存储为numpy.datetime64,时间单位为纳秒(可以通过检查ts.index.values 来检查)。将原始索引和bdate_range 生成的索引都转换为每日时间单位 ([D]) 并检查这两个数组的包含情况要快得多:

    import numpy as np
    import pandas
    
    def _get_days_array(index):
        "Convert the index to a datetime64[D] array"
        return index.values.astype('<M8[D]')
    
    def retain_business_days(ts):
        "Retain only the business days"
        tsdays = _get_days_array(ts.index) 
        bdays = _get_days_array(pandas.bdate_range(tsdays[0], tsdays[-1]))
        mask = np.in1d(tsdays, bdays)
        return ts[mask]
    

    【讨论】:

      猜你喜欢
      • 2013-01-18
      • 2015-05-13
      • 2017-03-16
      • 2014-09-13
      • 2020-06-27
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      • 2022-12-11
      相关资源
      最近更新 更多