从使用条件定义的变量行范围获取本地 max/min 值?

Getting local max/min values from variable row ranges defined with a condition?

我有以下问题。我正在研究 pandas 中的时间序列,其中有一列的直方图的值有时为正,有时为负。我需要为每个 window 的时间或范围不断变化的本地 max/min 值填充数据框的新列,因为它从正数变为正数的那一刻的行号之间的差异负到最后一次从负变为正,反之亦然。我还需要使用 pandas 或 numpy 方法来提高效率。

我一直在尝试制作一个辅助列,其中 df.loc 填充上次它从正变为负或反之亦然的行位置,如下所示:

df.loc[(df.Histogram.shift(1) > 0) & (df.Histogram < 0), 'LOC'] = df.index.get_loc(df.Histogram)
df.LOC.fillna(method='ffill')

(导致错误) 稍后尝试计算这些行位置之间的差异以定义当前 max/min 时间 window 然后应用 df.Histogram.rolling(loc_differences).max() 方法但我失败了让它工作,因为 .rolling 只接受一个固定的 window 值,并且因为我无法用位置填充列。 我知道必须有一个简单的解决方案。这是我正在寻找的示例:

Date             Histogram     Max/Min Value
01/02/2021         0.2            0.7
02/02/2021         0.3            0.7
03/02/2021         0.7            0.7
04/02/2021         0.2            0.7
05/02/2021        -0.2           -0.5
06/02/2021        -0.5           -0.5
07/02/2021        -0.1           -0.5
08/02/2021         0.4            0.4
09/02/2021         0.3            0.4
10/02/2021        -0.2           -0.2 
11/02/2021         0.2            0.7 
12/02/2021         0.7            0.7
13/02/2021         0.2            0.7
14/02/2021         0.3            0.7
15/02/2021         0.6            0.7
16/02/2021         0.2            0.7
17/02/2021        -0.2           -0.5
18/02/2021        -0.5           -0.5
19/02/2021        -0.1           -0.5
20/02/2021         0.4            0.4
21/02/2021         0.3            0.4
22/02/2021        -0.2           -0.3
23/02/2021        -0.1           -0.3 
24/02/2021        -0.3           -0.3
25/02/2021        -0.1           -0.3 
16/02/2021         0.2            0.3
27/02/2021         0.1            0.3    
28/02/2021         0.3            0.3

有解决办法吗?提前致谢。

这是一种将直方图数据分成 positive/negative 值组的简便方法。每次 grp 列递增,直方图列改变符号,所有具有相同 grp 值的行属于两次符号改变之间的相同间隔。

df['grp'] = (df.Histogram > 0).astype(int).diff().abs().cumsum().fillna(0)

df.head(10)
          Date  Histogram  grp
0   01/02/2021        0.2  0.0
1   02/02/2021        0.3  0.0
2   03/02/2021        0.7  0.0
3   04/02/2021        0.2  0.0
4   05/02/2021       -0.2  1.0
5   06/02/2021       -0.5  1.0
6   07/02/2021       -0.1  1.0
7   08/02/2021        0.4  2.0
8   09/02/2021        0.3  2.0
9   10/02/2021       -0.2  3.0

(df.Histogram > 0) 的选择是任意的,将零计为负值。 0.2, 0, 0.4, 0.3 的直方图序列将产生组 [0, 1, 2, 2]-0.2, 0, -0.4, -0.3 的序列将产生单个组。您必须确定这是否适合您的问题。

.fillna(0) 用于填充 .diff() 返回的第一行中出现的 NaN。请注意,零替换值的选择是合理的:如果符号从第一行到第二行发生变化,grp 将在第 2 行为 1,正确地将第 1 行放入其自己的组中。如果符号没有变化,grp 将在第 2 行为 0,将其与第 1 行正确分组。

您现在可以像这样使用 groupby 计算每组 minimum/maximum 个值

minmax = df.groupby('grp', as_index=False)['Histogram'].agg(
    {'hist_min': min, 'hist_max': max})
df = df.merge(minmax, on='grp')

df.head(10)
         Date  Histogram  grp  hist_min  hist_max
0  01/02/2021        0.2  0.0       0.2       0.7
1  02/02/2021        0.3  0.0       0.2       0.7
2  03/02/2021        0.7  0.0       0.2       0.7
3  04/02/2021        0.2  0.0       0.2       0.7
4  05/02/2021       -0.2  1.0      -0.5      -0.1
5  06/02/2021       -0.5  1.0      -0.5      -0.1
6  07/02/2021       -0.1  1.0      -0.5      -0.1
7  08/02/2021        0.4  2.0       0.3       0.4
8  09/02/2021        0.3  2.0       0.3       0.4
9  10/02/2021       -0.2  3.0      -0.2      -0.2

最后,您可以使用布尔索引assemble您想要的值

df['minmax'] = df.hist_min
df.loc[df.Histogram > 0, 'minmax'] = df.hist_max[df.Histogram > 0]

df.head(10)
         Date  Histogram  grp  hist_min  hist_max  minmax
0  01/02/2021        0.2  0.0       0.2       0.7     0.7
1  02/02/2021        0.3  0.0       0.2       0.7     0.7
2  03/02/2021        0.7  0.0       0.2       0.7     0.7
3  04/02/2021        0.2  0.0       0.2       0.7     0.7
4  05/02/2021       -0.2  1.0      -0.5      -0.1    -0.5
5  06/02/2021       -0.5  1.0      -0.5      -0.1    -0.5
6  07/02/2021       -0.1  1.0      -0.5      -0.1    -0.5
7  08/02/2021        0.4  2.0       0.3       0.4     0.4
8  09/02/2021        0.3  2.0       0.3       0.4     0.4
9  10/02/2021       -0.2  3.0      -0.2      -0.2    -0.2

整个过程尽可能向量化,所以性能应该不错