Slicing numpy array with another array

后端 未结 5 1194
青春惊慌失措
青春惊慌失措 2021-01-17 16:12

I\'ve got a large one-dimensional array of integers I need to take slices off. That\'s trivial, I\'d just do a[start:end]. The problem is that I need more of th

5条回答
  •  余生分开走
    2021-01-17 16:51

    This can (almost?) be done in pure numpy using masked arrays and stride tricks. First, we create our mask:

    >>> indices = numpy.arange(a.size)
    >>> mask = ~((indices >= start[:,None]) & (indices < end[:,None]))
    

    Or more simply:

    >>> mask = (indices < start[:,None]) | (indices >= end[:,None])
    

    The mask is False (i.e. values not masked) for those indices that are >= to the start value and < the end value. (Slicing with None (aka numpy.newaxis) adds a new dimension, enabling broadcasting.) Now our mask looks like this:

    >>> mask
    array([[ True, False,  True,  True,  True,  True,  True,  True,  True,
             True,  True,  True],
           [ True,  True,  True,  True,  True, False, False, False, False,
            False,  True,  True],
           [ True,  True,  True,  True,  True,  True,  True, False, False,
             True,  True,  True]], dtype=bool)
    

    Now we have to stretch the array to fit the mask using stride_tricks:

    >>> as_strided = numpy.lib.stride_tricks.as_strided
    >>> strided = as_strided(a, mask.shape, (0, a.strides[0]))
    >>> strided
    array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
           [ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
           [ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11]], dtype=int16)
    

    This looks like a 3x12 array, but each row points at the same memory. Now we can combine them into a masked array:

    >>> numpy.ma.array(strided, mask=mask)
    masked_array(data =
     [[-- 1 -- -- -- -- -- -- -- -- -- --]
     [-- -- -- -- -- 5 6 7 8 9 -- --]
     [-- -- -- -- -- -- -- 7 8 -- -- --]],
                 mask =
     [[ True False  True  True  True  True  True  True  True  True  True  True]
     [ True  True  True  True  True False False False False False  True  True]
     [ True  True  True  True  True  True  True False False  True  True  True]],
           fill_value = 999999)
    

    This isn't quite the same as what you asked for, but it should behave similarly.

提交回复
热议问题