【问题标题】:Is there a way to calculate forward looking rolling value in a Pandas dataframe for a varying number of rows?有没有办法计算 Pandas 数据框中不同行数的前瞻性滚动值?
【发布时间】:2018-10-22 20:21:26
【问题描述】:

我问的原因如下:

我有一个包含 15 分钟 OHLC 财务数据的时间序列。 我想计算的是给定任何数据点,在该数据点之后的特定时间范围内,未来的最高和最低价格(因此是前瞻性的)是多少。与该时间范围相关的确切行在行数或偏移位置上都不是固定的。

这里有一个例子来说明我的意思。

假设我在 4 月 28 日星期二的 23.45 处开盘高低收盘。 我想知道期间的最大值和最小值:

  1. 提前一天,因此需要对 4 月 29 日星期三的所有数据进行分组
  2. 提前一小时,所以是接下来的 4 行
  3. 提前一周,因此从 5 月 4 日(即星期一,即下周)开始,将是全部 672 行(4 行 x24 小时 x 7 天)。

正如您所看到的,该函数“需要知道”它的当前时间位置(在一天、一周、一个月中)如何确定我感兴趣的窗口(这是前瞻性的并被滑动变量偏移)。

有没有办法在不使用 for 循环和自定义函数的情况下做到这一点? 谢谢!

【问题讨论】:

标签: python-3.x pandas pandas-groupby


【解决方案1】:

df.rolling 可以接受字符串频率偏移作为其第一个参数。例如,

import numpy as np
import pandas as pd
np.random.seed(2018)

# Generate a DataFrame with an irregular DatetimeIndex
N = 20
start = np.datetime64('2018-01-01').astype('M8[s]').view('<i8')
end = np.datetime64('2018-02-01').astype('M8[s]').view('<i8')
timestamps = np.random.uniform(start, end, size=N)
timestamps.sort()
index = timestamps.astype('M8[s]')

df = pd.DataFrame(np.random.randint(10, size=(N, 4)), columns=list('OHLC'),
                  index=index)

这使用 2 天的窗口大小计算滚动平均值:

df.rolling('2D').mean()

这使用 7 天(即每周)窗口大小计算滚动平均值:

df.rolling('7D').mean()

1H 用于 1 小时窗口,1D 用于 1 天窗口,7D 用于 1 周窗口。

滚动窗口对应的行数不必是常数。


为了检查上面的代码是否产生了预期的结果,让我们确认一下 df.rolling('7D').mean() 的最后两行。

In [91]: df.rolling('7D').mean().tail(2)
Out[91]: 
                            O         H    L         C
2018-01-30 05:22:18  4.285714  3.000000  5.0  3.428571
2018-01-31 23:45:18  3.833333  2.833333  4.5  3.166667

最后一行对应于接管此 7 天 DataFrame 的均值:

In [93]: end = df.index[-1]; window = df.loc[end-pd.Timedelta(days=7):end]; window
Out[93]: 
                     O  H  L  C
2018-01-25 21:17:07  1  2  1  2
2018-01-26 22:48:38  6  0  3  1
2018-01-28 08:28:04  0  8  7  5
2018-01-29 02:48:53  8  0  2  3
2018-01-30 05:22:18  6  0  8  8
2018-01-31 23:45:18  2  7  6  0

In [94]: window.mean()
Out[94]: 
O    3.833333
H    2.833333
L    4.500000
C    3.166667
dtype: float64

window.mean() 中的值与df.rolling('7D').mean() 的最后一行中的值匹配。

同样,我们可以通过设置end = df.index[-2]来确认倒数第二行的结果:

In [95]: end = df.index[-2]; window = df.loc[end-pd.Timedelta(days=7):end]; window
Out[95]: 
                     O  H  L  C
2018-01-23 12:05:33  9  8  9  4
2018-01-24 11:16:36  0  3  5  1
2018-01-25 21:17:07  1  2  1  2
2018-01-26 22:48:38  6  0  3  1
2018-01-28 08:28:04  0  8  7  5
2018-01-29 02:48:53  8  0  2  3
2018-01-30 05:22:18  6  0  8  8

In [96]: window.mean()
Out[96]: 
O    4.285714
H    3.000000
L    5.000000
C    3.428571
dtype: float64

In [99]: window.mean().equals(df.rolling('7D').mean().loc[end])
Out[99]: True

请注意,窗口中的实际行数不同(6 对 7)。

【讨论】:

  • 然而,这并没有回答这个问题,该问题询问如何使用偏移量及时向前计算滚动窗口(因为 df.rolling('-7D') 不起作用)。我在别处找到了答案 - 在下面发布..
【解决方案2】:

根据this answer,在使用滚动功能之前暂时反转时间序列。

这是一个使用这个想法的例子(可以与任何时间序列一起使用,偏移量和聚合函数都一样):

让我们生成一些随机的不规则索引时间序列:

import pandas as pd
import numpy as np
    
length = 15
# generate 15 unique days within 90 days from '2020-01-01'  
dates = np.datetime64('2020-01-01') + np.random.choice(90, size = length, replace = False)
ts = pd.Series(np.random.randint(0,9, size = length), index = dates).sort_index()

In[1]: ts
Out[1]: 
2020-01-04    7
2020-01-10    2
2020-01-12    4
2020-01-19    8
2020-02-04    3
2020-02-05    8
2020-02-07    5
2020-02-19    7
2020-02-24    6
2020-02-25    4
2020-03-01    8
2020-03-04    0
2020-03-14    6
2020-03-15    7
2020-03-28    6
dtype: int32

现在要找到 1 周偏移量 FORWARD 内的每周最大值,我们只需要在反转序列上使用带有 '7D' 偏移量的滚动函数,然后将结果反转回来:

In[2]: ts[::-1].rolling(window = '7D').max()[::-1]
Out[2]: 
2020-01-04    7.0
2020-01-10    4.0
2020-01-12    4.0
2020-01-19    8.0
2020-02-04    8.0
2020-02-05    8.0
2020-02-07    5.0
2020-02-19    7.0
2020-02-24    8.0
2020-02-25    8.0
2020-03-01    8.0
2020-03-04    0.0
2020-03-14    7.0
2020-03-15    7.0
2020-03-28    6.0

【讨论】:

    猜你喜欢
    • 2019-09-08
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多