Extend numpy mask by n cells to the right for each bad value, efficiently

前端 未结 7 1347
[愿得一人]
[愿得一人] 2021-02-15 15:39

Let\'s say I have a length 30 array with 4 bad values in it. I want to create a mask for those bad values, but since I will be using rolling window functions, I\'d also like a f

7条回答
  •  暗喜
    暗喜 (楼主)
    2021-02-15 15:47

    This could also be considered a morphological dilation problem, using here the scipy.ndimage.binary_dilation:

    def dilation(a, n):
        m = np.isnan(a)
        s = np.full(n, True, bool)
        return ndimage.binary_dilation(m, structure=s, origin=-(n//2))
    

    Note on origin: this argument ensures the structure (I would call it a kernel) starts off a bit to the left of the input (your mask m). Normally the value at out[i] would be the dilation with the center of structure (which would be structure[n//2]) at in[i], but you want the structure[0] to be at in[i].

    You can also do this with a kernel that is padded on the left with Falses, which is what would be required if you used the binary_dilation from scikit-image:

    def dilation_skimage(a, n):
        m = np.isnan(a)
        s = np.zeros(2*n - n%2, bool)
        s[-n:] = True
        return skimage.morphology.binary_dilation(m, selem=s)
    

    Timing doesn't seem to change too much between the two:

    dilation_scipy
    small:    10 loops, best of 3: 47.9 ms per loop
    large: 10000 loops, best of 3: 88.9 µs per loop
    
    dilation_skimage
    small:    10 loops, best of 3: 47.0 ms per loop
    large: 10000 loops, best of 3: 91.1 µs per loop
    

提交回复
热议问题