如何在numpy中计算一维数组的移动(或滚动)百分位数/分位数?

3
在pandas中,我们有pd.rolling_quantile()。在numpy中,我们有np.percentile(),但我不确定如何做它的滚动/移动版本。
为了解释我所说的移动/滚动百分位数/分位数:
给定数组[1, 5, 7, 2, 4, 6, 9, 3, 8, 10],窗口大小为3的移动分位数0.5(即移动百分位数50%)是:
1
5 - 1 5 7 -> 0.5 quantile = 5
7 - 5 7 2 ->                5
2 - 7 2 4 ->                4
4 - 2 4 6 ->                4
6 - 4 6 9 ->                6
9 - 6 9 3 ->                6
3 - 9 3 8 ->                8
8 - 3 8 10 ->               8
10

所以答案是 [5, 5, 4, 4, 6, 6, 8, 8]。为了使结果序列与输入序列长度相同,一些实现会插入NaNNone,而pandas.rolling_quantile()允许通过较小的窗口计算前两个分位数值。


你能展示一下样本数据和期望的输出吗? - BENY
刚刚完成了。希望这样能够澄清我的目标。@Wen - Roy
请检查答案 :-) - BENY
这是你需要的吗? - BENY
2个回答

7
series = pd.Series([1, 5, 7, 2, 4, 6, 9, 3, 8, 10])

In [194]: series.rolling(window = 3, center = True).quantile(.5)

Out[194]: 
0      nan
1   5.0000
2   5.0000
3   4.0000
4   4.0000
5   6.0000
6   6.0000
7   8.0000
8   8.0000
9      nan
dtype: float64

默认情况下,CenterFalse。因此,您需要手动将其设置为True,以便分位数计算窗口对称地包含当前索引。


3
我们可以使用np.lib.stride_tricks.as_strided创建滑动窗口,实现为一个函数strided_app
In [14]: a = np.array([1, 5, 7, 2, 4, 6, 9, 3, 8, 10]) # input array

In [15]: W = 3 # window length

In [16]: np.percentile(strided_app(a, W,1), 50, axis=-1)
Out[16]: array([ 5.,  5.,  4.,  4.,  6.,  6.,  8.,  8.])

为了使其与输入具有相同的长度,我们可以使用np.concatenate或更简单的np.pad填充NaNs。因此,对于W=3,它将是-
In [39]: np.pad(_, 1, 'constant', constant_values=(np.nan)) #_ is previous one
Out[39]: array([ nan,   5.,   5.,   4.,   4.,   6.,   6.,   8.,   8.,  nan])

标记为答案,因为它提供了解决我的问题的方法。只是好奇,您的方法是否可以扩展到执行pandas.rolling_quantile()min_periods部分(即在开头创建两个额外的步幅,每个步幅都有更少的成员)?@Divakar - Roy
1
@Roy 是的。使用NaN对输入数组进行填充,再使用np.nanpercentile函数。 - Divakar
太好了。谢谢@Divakar。 - Roy
1
这种方法可能会导致大型输入数组的内存溢出。 - Prokhozhii

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接