首页 > 解决方案 > 有没有办法计算 Pandas 数据框中不同行数的前瞻性滚动值?

问题描述

我问的原因如下:

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

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

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

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

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

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

标签: python-3.xpandaspandas-groupby

解决方案


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()

用于1H1 小时窗口、1D1 天窗口和7D1 周窗口。

对应于滚动窗口的行数不必是恒定的。


为了检查上面的代码是否产生了预期的结果,让我们确认最后两行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)。


推荐阅读