数组的滚动最小值,以便第一个值是 window 的最小值,而不是 NaN

Rolling minimum of an array so that first values are minimum of window, not NaN

到目前为止,我一直在使用 panda'fying 我的数组,以便我可以使用 Panda 的滚动 + min() 功能,我使用的 window of window 宽度为 3。

import pandas as pd
import numpy as np

q = np.array([ 4.71858472,  4.5252853 ,  3.43745458,  1.978533  , -0.50446801,
   -0.25213346,  0.04942399, -0.76639228,  0.17852748,  0.58374693])

df_q = pd.DataFrame(q,columns=['min_q'])

df_min = df_q.rolling(3,min_periods=1).min()

我得到的是 Pandas 如果未指定 min_periods 则为前 2 个返回值插入 NaN 值(有意义),或者在指定时仅采用指定值(也有道理)。我想知道的是,是否有可能获得一个返回系列,其中返回集的初始值等于第一个 window 的最低值,而不是最小周期的值。

我得到的:

array([[ 4.71858472], [ 4.5252853 ],[ 3.43745458],[ 1.978533  ],[-0.50446801],[-0.50446801],[-0.50446801],[-0.76639228],[-0.76639228],[-0.76639228]])

我想要的:

array([[ 3.43745458], [ 3.43745458 ],[ 1.978533],[ 0.50446801 ],[-0.50446801],[-0.50446801],[-0.76639228],[-0.76639228],[-0.76639228],[0.17852748]])

这甚至可以在 Pandas 中完成吗?

我觉得你需要DataFrame.bfill

>>> df_min = df_q.rolling(3).min().bfill()
>>> df_min
      min_q
0  3.437455
1  3.437455
2  3.437455
3  1.978533
4 -0.504468
5 -0.504468
6 -0.504468
7 -0.766392
8 -0.766392
9 -0.766392

如果你追求性能,可以使用scipy.ndimage.filters.minimum_filter1d:

import numpy as np
import pandas as pd
from scipy.ndimage.filters import minimum_filter1d

q = np.array([ 4.71858472,  4.5252853 ,  3.43745458,  1.978533  , -0.50446801,
   -0.25213346,  0.04942399, -0.76639228,  0.17852748,  0.58374693])

def rolling_scipy(a, W):
    hW = (W-1)//2 
    out = minimum_filter1d(a, size=W, origin=hW)
    out[:W-1] = out[W-1]
    return out

%timeit rolling_scipy(q, 3)
12.8 µs ± 1.32 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

def rolling_pandas(a, W):
    df = pd.DataFrame(a, columns=['min_q'])
    return df.rolling(W).min().bfill()

%timeit rolling_pandas(q, W)
1.41 ms ± 146 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)