2
A = np.array([[4.0, 3, 2],
              [1, 2, 3],
              [0, -1, 5]])

shift = np.array([1,2,1])

out = np.array([[3, 2, np.nan],
              [3, np.nan, np.nan],
              [-1, 5, np.nan]])

I want to left shift the 2D numpy array towards the left for each row independently as given by the shift vector and impute the right with Nan.

Please help me out with this

Thanks

vvv
  • 461
  • 1
  • 5
  • 14

3 Answers3

0
import numpy as np

A = np.array([[4, 3, 2],
              [1, 2, 3],
              [0, -1, 5]])

shift = np.array([1,2,1])


x,y = A.shape
res = np.full(x*y,np.nan).reshape(x,y)

for i in range(x):
    for j in range(y):
        res[i][:(y-shift[i])]=A[i][shift[i]:]
print(res)
islam abdelmoumen
  • 662
  • 1
  • 3
  • 9
0

Using Roll rows of matrix Ref

from skimage.util.shape import view_as_windows as viewW
import numpy as np


A = np.array([[4, 3, 2],
              [1, 2, 3],
              [0, -1, 5]])

shift = np.array([1,1,1])

p = np.full((A.shape[0],A.shape[1]-1),np.nan)
a_ext = np.concatenate((A,p,p),axis=1)


n = A.shape[1]
shifted =viewW(a_ext,(1,n))[np.arange(len(shift)), -shift + (n-1),0]


print(shifted)

output #

[[ 3.  2. nan]
 [ 2.  3. nan]
 [-1.  5. nan]]
0

you should just use a for loop and np.roll per row.

import numpy as np
A = np.array([[4, 3, 2],
              [1, 2, 3],
              [0, -1, 5]]).astype(float)

shift = np.array([1,2,1])

out = np.copy(A)
for i,shift_value in enumerate(shift):
    out[i,:shift_value] = np.nan
    out[i,:] = np.roll(out[i,:], -shift_value, 0)
print(out)
[[ 3.  2. nan]
 [ 3. nan nan]
 [-1.  5. nan]]

while someone might think that reducing the calls to np.roll will help, it won't because this is exactly the way np.roll is implemented internally, and you'll have 2 loops in your code instead of 1.

Ahmed AEK
  • 8,584
  • 2
  • 7
  • 23
  • @vvv not with numpy alone ... you'll have to use something like cython or numba, for almost the same performance. – Ahmed AEK Dec 07 '22 at 11:29