I have an interger d and boolean array, say
M = array([[ True, False, False, True],
[False, True, False, False],
[False, False, False, False],
[False, False, False, True]])
Now I want to create a new array from M with the following rule: Trues stay and the next d positions left of a True also become True. I came up with this:
newarray = np.full_like(M,False)
for r,row in enumerate(M[1:],1):
for i,boo in enumerate(row):
if boo:
newarray[max(0,r-d):r,i] = True
I have the feeling there is a more efficient way of doing this using numpy commands; probably using np.where.
EDIT: e.g. d = 1, the result should be
M = array([[ True, False, True, True],
[ True, True, False, False],
[False, False, False, False],
[False, False, True, True]])
for d = 2, the result should be
M = array([[ True, True, True, True],
[ True, True, False, False],
[False, False, False, False],
[False, True, True, True]])
You can use a 2D convolution with scipy.signal.convolve2d:
from scipy.signal import convolve2d
d = 2
kernel = np.repeat([1, 1, 0], [d, 1, d])[None]
# array([[1, 1, 1, 0, 0]])
out = convolve2d(M, kernel, mode='same') > 0
Output for d = 1:
array([[ True, False, True, True],
[ True, True, False, False],
[False, False, False, False],
[False, False, True, True]])
Output for d = 2:
array([[ True, True, True, True],
[ True, True, False, False],
[False, False, False, False],
[False, True, True, True]])
Similar to @mozway, but with numpy's sliding_window_view and pad:
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view as swv
M = array([[ True, False, False, True],
[False, True, False, False],
[False, False, False, False],
[False, False, False, True]])
d = 2
out = swv(np.pad(M, ((0, 0), (0, d))), d + 1, axis=1).any(axis=2)
out:
array([[ True, True, True, True],
[ True, True, False, False],
[False, False, False, False],
[False, True, True, True]])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With