【问题标题】:Rolling windows in Pandas: How to wrap around with DatetimeIndex?Pandas 中的滚动窗口:如何使用 DatetimeIndex 环绕?
【发布时间】:2023-01-28 18:03:36
【问题描述】:

我有一个 DataFrame,其中索引是一个每日频率的 DatetimeIndex。它包含 365 行,一年中的每一天。计算滚动总和时,前几个元素始终为 NaN(正如预期的那样),但我希望它们具有实际值。

例如,如果使用 3 个样本的滚动窗口,则 1 月 1 日的值应为 12 月 30 日、12 月 31 日和 1 月 1 日的总和。同样,1 月 2 日的值应为 12 月 31 日、1 月 1 日、和 1 月 2 日。

我查看了 Pandas 中滚动函数的所有参数,但找不到任何可以提供这种包装的东西。任何帮助,将不胜感激。下面的代码是说明滚动行为的最小示例。

import numpy as np
import pandas as pd

fake_data = pd.DataFrame(index=pd.date_range('2022-1-1', '2022-12-31', freq='D'),
                         data=np.random.random(365))
rolling_fake_data = fake_data.rolling(3).sum()

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您基本上是在要求一个没有开始或结束的循环数据对象。不确定是否存在!

    我能想到的最好的解决方法是在开始之前重复系列的结尾。

    n = 3
    rolling_fake_data = (
        pd.concat([fake_data[-n:], fake_data])
    ).rolling(n).sum()[n:]
    
    # Test
    assert(rolling_fake_data.loc["2022-01-01", 0] ==
        fake_data.loc[["2022-12-30", "2022-12-31", "2022-01-01"], 0].sum())
    

    【讨论】:

      【解决方案2】:

      您可以只传递给滚动 min_periods 参数。它看起来像

      import numpy as np
      import pandas as pd
      
      fake_data = pd.DataFrame(index=pd.date_range('2022-1-1', '2022-12-31', freq='D'),
                               data=np.random.random(365))
      rolling_fake_data = fake_data.rolling(3, min_periods=0).sum()
      

      将会发生的情况是,对于没有完整大小的窗口的第一行,即 3,将使用到该点的窗口执行总和,因此第一个元素将是第一个元素本身,第二个元素将是 first+second,从第三个开始,窗口将具有完整大小,因此将按预期进行计算。

      【讨论】:

      • 我不认为这符合 OP 的要求。见问题的第 3 段。
      • 鉴于这个问题,我认为这是最好的答案,因为无论如何都没有2021-12-31的数据......
      【解决方案3】:

      您可以在中心参数设置为 True 的情况下使用滚动功能。这将确保窗口以每个元素为中心,其中包括元素本身及其前后的元素。例如,如果您的窗口大小为 3,则第一个元素将是第一个元素和它前面两个元素的总和,在您的情况下,这将是前一年的最后两个元素。

      import pandas as pd
      import numpy as np
      
      date_rng = pd.date_range(start='1/1/2020', end='12/31/2020', freq='D')
      df = pd.DataFrame(date_rng, columns=['date'])
      df['data'] = np.random.randint(0,100,size=(len(date_rng)))
      df.set_index('date', inplace=True)
      df['rolling_sum'] = df['data'].rolling(window=3, center=True).sum()
      

      【讨论】:

        猜你喜欢
        • 2018-02-19
        • 2018-01-28
        • 1970-01-01
        • 2016-11-25
        • 2018-12-17
        • 2021-06-13
        • 2014-09-12
        • 1970-01-01
        相关资源
        最近更新 更多