Python / NumPy: implementation of the current amount (but not quite)

Here are two arrays of equal length, one of which contains data, one of which contains results, but is initially set to zero, for example:

a = numpy.array([1, 0, 0, 1, 0, 1, 0, 0, 1, 1])
b = numpy.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

I would like to calculate the sum of all possible subsets of three adjacent elements in a. If the sum is 0 or 1, the three corresponding elements in b remain unchanged; only if the sum exceeds 1, then the three corresponding elements from b are set to 1, so that after calculating b becomes

array([0, 0, 0, 1, 1, 1, 0, 1, 1, 1])

A simple loop will do this:

for x in range(len(a)-2):
    if a[x:x+3].sum() > 1:
        b[x:x+3] = 1

After that, b has the desired shape.

I have to do this for a lot of data, so speed is a problem. Is there a faster way in NumPy to perform the operation above?

(I understand that this looks like a convolution, but not quite the same).

+5
3

, , 1, , , "":

b = numpy.convolve(a, [1, 1, 1], mode="same") > 1
b = b | numpy.r_[0, b[:-1]] | numpy.r_[b[1:], 0]

Python, , , .

:

kernel = [1, 1, 1]
b = numpy.convolve(a, kernel, mode="same") > 1
b = numpy.convolve(b, kernel, mode="same") > 0

SciPy, -

b = numpy.convolve(a, [1, 1, 1], mode="same") > 1
b = scipy.ndimage.morphology.binary_dilation(b)

: , , , -, :

b = numpy.convolve(a, kernel) > 1
b[:-1] |= b[1:]  # Shift and "smearing" to the *left* (smearing with b[1:] |= b[:-1] does not work)
b[:-1] |= b[1:]  # … and again!
b = b[:-2]

200 , . EOL , , , NumPy.

+6

"" :

>>> a0 = a[:-2]
>>> a1 = a[1:-1]
>>> a2 = a[2:]
>>> a_large_sum = a0 + a1 + a2 > 1

b , -, , " a_large_sum True": a_large_sum , a (, , ):

>>> a_large_sum_0 = np.hstack([a_large_sum, [False, False]])
>>> a_large_sum_1 = np.hstack([[False], a_large_sum, [False]])
>>> a_large_sum_2 = np.hstack([[False, False], a_large_sum])

b :

>>> b = a_large_sum_0 | a_large_sum_1 | a_large_sum_2

, , , NumPy.

PS. , Sven, , Sven-; , . Sven (double convolve()) , .

+2

NumPy stride_tricks. Sven (. ), , () , (.. a):

shape = (len(a)-2,3)
strides = a.strides+a.strides
a_strided = numpy.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)
b = np.r_[numpy.sum(a_strided, axis=-1) > 1, False, False]
b[2:] |= b[1:-1] | b[:-2]

(. ) .

. a , -. , , (.. , ). , .

3, a 2 ( -2 nd).

The list of steps contains the steps in bytes that the new array must take a_stridedin order to go to the next element in each shape size. If you set them equal, it means that a_strided[0,1]they a_strided[1,0]will be equal a[1], which is what we want. In a regular array, this is not so (the first step would be "the size of the first time of the length-array-first dimension (= form [0])", but in this case we can make good use of it.

I'm not sure that I explained all this well, but just print a_strided and you will see what the result is and how easy the operation makes it.

+1
source

All Articles