Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an array by shifting values

Tags:

python

numpy

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]])
like image 413
Lilly Avatar asked Feb 03 '26 21:02

Lilly


2 Answers

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]])
like image 86
mozway Avatar answered Feb 05 '26 11:02

mozway


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]])
like image 23
Chrysophylaxs Avatar answered Feb 05 '26 11:02

Chrysophylaxs



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!