python 是否使用自定义步骤滚动带时间戳的DataFrame上的窗口?

mwkjh3gx  于 2023-01-04  发布在  Python
关注(0)|答案(1)|浏览(118)

我已经摆弄pandas.DataFrame.rolling一段时间了,我还没有能够达到我想要的结果,所以在我写一个自定义窗口函数之前,我想我会问我是否错过了什么。
我有一个postgresql数据,其复合索引为(time, node),该数据已被读入pandas.DataFrame,其中time是某个日期的某个小时。(或任何任意天数),例如开始于2022-12-26 00:00:00并结束于2022-12-27 23:00:00,然后在该窗口上执行操作以返回新的,窗口应该向前移动一个完整的日历日期,这是我失败的地方。

| time                  | node  | value  |
| --------------------- | ----- | ------ |
| 2022-12-26 00:00:00   | 123   | low    |
| 2022-12-26 01:00:00   | 123   | med    |
| 2022-12-26 02:00:00   | 123   | low    |
| 2022-12-26 03:00:00   | 123   | high   |
| ...                   | ...   | ...    |
| 2022-12-26 00:00:00   | 999   | low    |
| 2022-12-26 01:00:00   | 999   | low    |
| 2022-12-26 02:00:00   | 999   | low    |
| 2022-12-26 03:00:00   | 999   | med    |
| ...                   | ...   | ...    |
| 2022-12-27 00:00:00   | 123   | low    |
| 2022-12-27 01:00:00   | 123   | med    |
| 2022-12-27 02:00:00   | 123   | low    |
| 2022-12-27 03:00:00   | 123   | high   |

当我使用类似于df.rolling(window=pd.Timedelta('2days')的东西时,窗口会逐小时向前移动,而不是从下一个日历日期开始。
我尝试过使用min_periods,但它似乎不适用于我的数据,从长远来看也是不可接受的,因为每个窗口的预期观测数并不是固定的。step参数在这种情况下似乎也是无用的,因为我对窗口使用的是偏移量而不是整数。
我所寻找的行为在pandas.DataFrame.rolling上可行吗?还是我必须在别处寻找/编写自己的窗口函数?
如有任何指导,将不胜感激。谢谢!

weylhg0b

weylhg0b1#

因此,据我所知,您希望创建长度为ndays的窗口,下一个窗口应该从第二天开始。
给定某个 Dataframe ,共5天,索引之间的频率为1H:

import pandas as pd
import numpy as np

periods = 23 * 5
df = pd.DataFrame(
    {'value': list(range(periods))},
    index=pd.date_range('2022-12-16', periods=periods, freq='H')
)
d = np.random.choice(
    pd.date_range('2022-12-16', periods=periods, freq='H'),
    int(periods * 0.25)
)
df = df.drop(index=d)
df.head(5)          
>>>                  value
2022-12-16 00:00:00      0
2022-12-16 01:00:00      1
2022-12-16 02:00:00      2
2022-12-16 04:00:00      4
2022-12-16 05:00:00      5

我随机删除了一些索引来模拟缺失数据,我们可以使用df.resampledocs)来按天对数据进行分组(不考虑缺失数据):

days = df.resample('1d')
print(days.get_group('2022-12-16'))
>>>                  value
2022-12-16 00:00:00      0
2022-12-16 01:00:00      1
2022-12-16 02:00:00      2
2022-12-16 04:00:00      4
2022-12-16 05:00:00      5
2022-12-16 06:00:00      6
2022-12-16 07:00:00      7
2022-12-16 08:00:00      8
2022-12-16 09:00:00      9
2022-12-16 11:00:00     11
2022-12-16 12:00:00     12
2022-12-16 13:00:00     13
2022-12-16 14:00:00     14
2022-12-16 15:00:00     15
2022-12-16 17:00:00     17
2022-12-16 18:00:00     18
2022-12-16 19:00:00     19
2022-12-16 21:00:00     21
2022-12-16 22:00:00     22
2022-12-16 23:00:00     23

现在,我们只需要以“滑动”的方式迭代这些天,包more-itertools有一些有用的函数,比如windowed,我们可以很容易地控制窗口的大小(这里使用ndays):

from more_itertools import windowed
ndays = 2
windows = [
    pd.concat([w[1] for w in window])
    for window in windowed(days, ndays)
]

打印每个窗口的第一个和最后一个索引将返回:

for window in windows:
    print(window.iloc[[0, -1]])

>>>                  value
2022-12-16 00:00:00      0
2022-12-17 23:00:00     47
                     value
2022-12-17 00:00:00     24
2022-12-18 23:00:00     71
                     value
2022-12-18 00:00:00     48
2022-12-19 23:00:00     95
                     value
2022-12-19 01:00:00     73
2022-12-20 18:00:00    114

此外,您可以在windowed中设置step,以控制窗口之间的步长。

相关问题