3

I am not sure what key-word to search for so if it has been already asked please link the response and close this thread.

I am trying to shift the non-zero entries of a numpy array by a fixed direction, for instance, imagine I have a 2d array:

0 1 2 0
0 3 0 0
0 0 0 0
0 0 0 0

Shifting it by (1,1) would produce the following array:

0 0 0 0
0 0 1 2
0 0 3 0
0 0 0 0

Let's say if the non-zero entries goes out of bound they're simply dropped. How might I do this?

edit: aparently some duplicate from this? Shift elements in a numpy array I don't really see why are they the same question at all because that one talks about looping the things out of bound around, so it's more of a "rolling" action rather than shifting. Also I liked the solution here, it is very simple and readable.

edit again: fixed some formats

4
  • 1
    Save for the edge behaviour you might be looking for np.roll. You could also just construct a new array from a slice. Commented Jul 2, 2017 at 19:41
  • Please edit you values to be 1,2,3 instead of 2,2,2 so we can see what kind of shift you want, this can be many different things right now Commented Jul 2, 2017 at 19:44
  • 1
    Something like shift=(1,1); new=np.zeros_like(old); new[shift[0]:,shift[1]:]=old[:-shift[0],:-shift[1]] give or take a few off-by-one errors. Commented Jul 2, 2017 at 19:47
  • 1
    Possible duplicate of Shift elements in a numpy array Commented Jul 2, 2017 at 20:10

2 Answers 2

6

Using roll method from numpy.

>>> import numpy as np
>>> m
array([[0, 1, 2, 0],
       [0, 3, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])
>>> m = np.roll(m, 1, axis=0) # shift 1 place in horizontal axis
>>> m = np.roll(m, 1, axis=1) # shift 1 place in vertical axis
>>> m
array([[0, 0, 0, 0],
       [0, 0, 1, 2],
       [0, 0, 3, 0],
       [0, 0, 0, 0]])

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.roll.html

Sign up to request clarification or add additional context in comments.

Comments

2

To simply manage the edges, you can enlarge your array in a bigger one :

square=\
array([[0, 2, 2, 0],
       [0, 2, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]], dtype=int64)

n,m=square.shape
bigsquare=np.zeros((3*n,3*m),square.dtype) 
bigsquare[n:2*n,m:2*m]=square

Then shift is just a view :

def shift(dx,dy):
    x=n-dx
    y=m-dy
    return bigsquare[x:x+n,y:y+m]

print(shift(1,1))

#[[0 0 0 0]
# [0 0 2 2]
# [0 0 2 0]
# [0 0 0 0]]

3 Comments

It's a view of a copy which is not particularly informative.
@AndrasDeak ah i didn't meant to edit in place anyways, a copy is just fine for me as I kept most of my things functional anyways
@EvanPu I know, you can't really do this any other way. I just reflected on B. M.'s "shift is just a view" remark.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.