使用numpy.lib.stride_tricks.as_strided滑动NaN填充元素的窗口

时间:2017-01-07 10:20:49

标签: python numpy

考虑数组a

import numpy as np
import pandas as pd

np.random.seed([3,1415])
a = np.random.randint(100, size=10)
print(a)

[11 98 74 90 15 55 13 11 13 26]

我正在使用as_strided from numpy.lib.stride_tricks import as_strided

当我使用它来提供如下滚动窗口时

as_strided(a, shape=(len(a), 5), strides=(8, -8))

[[11  0  0  0  0]
 [98 11  0  0  0]
 [74 98 11  0  0]
 [90 74 98 11  0]
 [15 90 74 98 11]
 [55 15 90 74 98]
 [13 55 15 90 74]
 [11 13 55 15 90]
 [13 11 13 55 15]
 [26 13 11 13 55]]

这几乎是完美的。我希望在顶部三角形中使用np.nan而不是零。

我想要这个

[[ 11.  nan  nan  nan  nan]
 [ 98.  11.  nan  nan  nan]
 [ 74.  98.  11.  nan  nan]
 [ 90.  74.  98.  11.  nan]
 [ 15.  90.  74.  98.  11.]
 [ 55.  15.  90.  74.  98.]
 [ 13.  55.  15.  90.  74.]
 [ 11.  13.  55.  15.  90.]
 [ 13.  11.  13.  55.  15.]
 [ 26.  13.  11.  13.  55.]]

是否有方便的方法告诉as_strided填写np.nan而不是

1 个答案:

答案 0 :(得分:3)

诀窍是先加入NaNs然后加大力度。通过使用适当的步幅,可以有两种方式向前和向后。设置所需输出的方式,我们需要沿每行向后跨步。另一种方法是向前迈进,获得2D输出并最终翻转列,尽管它会慢一点。因此,使用前向方法,我们将像往常一样沿着每一行向前迈步,向后跨步一步就是一个负步幅。

因此,strides的两种方法是 -

from numpy.lib.stride_tricks import as_strided as strided 

def strided_nan_filled(a, W):
    a_ext = np.concatenate(( np.full(W-1,np.nan) ,a))
    n = a_ext.strides[0]
    return strided(a_ext, shape=(a.size,W), strides=(n,n))[:,::-1]

def strided_nan_filled_v2(a, W):
    a_ext = np.concatenate(( np.full(W-1,np.nan) ,a))
    n = a_ext.strides[0]
    return strided(a_ext[W-1:], shape=(a.size,W), strides=(n,-n))

示例运行 -

In [42]: a
Out[42]: array([11, 98, 74, 90, 15, 55, 13, 11, 13, 26])

In [43]: strided_nan_filled(a, 5)
Out[43]: 
array([[ 11.,  nan,  nan,  nan,  nan],
       [ 98.,  11.,  nan,  nan,  nan],
       [ 74.,  98.,  11.,  nan,  nan],
       [ 90.,  74.,  98.,  11.,  nan],
       [ 15.,  90.,  74.,  98.,  11.],
       [ 55.,  15.,  90.,  74.,  98.],
       [ 13.,  55.,  15.,  90.,  74.],
       [ 11.,  13.,  55.,  15.,  90.],
       [ 13.,  11.,  13.,  55.,  15.],
       [ 26.,  13.,  11.,  13.,  55.]])

运行时测试 -

In [74]: a = np.random.randint(0,9,(1000))

In [75]: %timeit strided_nan_filled(a, 5)
10000 loops, best of 3: 30.1 µs per loop

In [76]: %timeit strided_nan_filled_v2(a, 5)
10000 loops, best of 3: 28.7 µs per loop