1

I am getting some strange results from the following but am relatively new to python so may be messing something up. The following:

import numpy as np

a = np.array([1,2,3,4])
print(a)

old_a = a

for x in range(0,1):
   new_a = old_a
   new_a[0] = old_a[1]
   new_a[1] = old_a[2]
   new_a[2] = old_a[3]
   new_a[3] = old_a[0]
   print(new_a)

[1 2 3 4]
[2 3 4 2]

I would have expected the second array to be [2 3 4 1].

However, if I create a new array as with the "clean" def below, it seems to work

def clean(b_in):
   out = np.zeros(4)
   for x in range(0,4):
       out[x] = b_in[x]
   return out

b = np.array([1,2,3,4])
print(b)

new_b = b

for x in range(0,1):
   old_b = clean(new_b)
   new_b[0] = old_b[1]
   new_b[1] = old_b[2]
   new_b[2] = old_b[3]
   new_b[3] = old_b[0]
   print(new_b) 

[1 2 3 4]
[2 3 4 1]

What am I missing and how do I avoid the clean def?

Thanks

**** Updated question below ****

Thanks for the responses. So, notwithstanding the response regarding the roll function below, is this the best way to do achieve the same as the roll function?

import numpy as np

a = np.array([1,2,3,4])
print(a)

old_a = a

for x in range(0,10):
   new_a = old_a.copy()
   new_a[0] = old_a[1]
   new_a[1] = old_a[2]
   new_a[2] = old_a[3]
   new_a[3] = old_a[0]
   old_a = new_a.copy()
   print(new_a)

Thanks again

EDIT

This is what I settled on:

import numpy as np

a = np.array([1,2,3,4])
print(a)

old_a = a
new_a = np.zeros_like(old_a)

for x in range(0,10):
    new_a[0] = old_a[1]
    new_a[1] = old_a[2]
    new_a[2] = old_a[3]
    new_a[3] = old_a[0]
    old_a = new_a.copy()
    print(new_a)

[1 2 3 4]
[2 3 4 1]
[3 4 1 2]
[4 1 2 3]
[1 2 3 4]
[2 3 4 1]
[3 4 1 2]
[4 1 2 3]
[1 2 3 4]
[2 3 4 1]
[3 4 1 2]

Thank you all!

6
  • Your assignment new_a = old_a is the problem, as new_a points now to the same memory as old_a. If you want to copy a numpy array, use new_a = old_a.copy(). Commented Oct 14, 2017 at 20:22
  • Furthermore, as you are overwriting all elements anyhow, you don't need to copy, but you can create an array of zeros of the same shape with new_b = np.zeros_like(old_b), or an empty array with new_b = np.empty_like(old_b). Commented Oct 14, 2017 at 20:34
  • No, you are making an unnecessary copy in the first line under for. It is better to declare new_a outside of the loop, then one copy suffices. And please use four spaces :). Commented Oct 14, 2017 at 20:44
  • @Austin check the updated answer for a better way of doing this Commented Oct 14, 2017 at 20:47
  • Ah, got it now. Thanks a lot, Chiel Commented Oct 14, 2017 at 20:51

3 Answers 3

2

Even though this answer is not answering your question, for your specific case there is a much simpler solution, if shifting the elements by one is what you are searching for. It avoids the complexity in which you are getting stuck, and it simplifies things.

import numpy as np

a = np.array([1,2,3,4])
b = np.roll(a, -1)
print(a, b)

Output

[1 2 3 4] [2 3 4 1]
Sign up to request clarification or add additional context in comments.

1 Comment

For the downvoter: I know it is not an answer to the question exactly, and I have already given my comments under the post. I just thought to give a tip on how to address this specific case in the best numpy way.
0

When you're changing the values of new_a you're also changing the values of old_a as you're doing shallow copy and not deepcopy by assigning new_a = old_a:

new_a[0] = old_a[1]
new_a[1] = old_a[2]
new_a[2] = old_a[3]
#old_a[0] is already old_a[1], as you reassigned it on line #1
new_a[3] = old_a[0] 

Here's the difference between shallow and deepcopy as in Python Docs:

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

You can avoid your clean def by using deepcopy or copy() in case of numpy array:

import numpy as np
#from copy import deepcopy #for python lists
a = np.array([1,2,3,4])
print(a)
old_a = a
for x in range(0,1):
   #new_a = deepcopy(old_a) #for python lists
   new_a = old_a.copy() # for numpy array
   new_a[0] = old_a[1]
   new_a[1] = old_a[2]
   new_a[2] = old_a[3]
   new_a[3] = old_a[0]
   print(new_a)

EDIT

After your updated question, looks like you want to update the old_a itself, so no need to copy it to new array, you can simply achieve what you're trying to do like this:

import numpy as np
a = np.array([1,2,3,4])
print(a)
old_a = a
for x in range(0,1):
   old_a[0], old_a[1], old_a[2], old_a[3] = old_a[1], old_a[2], old_a[3], old_a[0]
   print(old_a)

10 Comments

I don't think you need to use deepcopy here. Numpy has its own copy function that is readily available. See my comment above.
ohh forgot he's using numpy, updated the answer thanks :)
@AshishRanjan -- why do you need a 'for' loop?
@AshishRanjan look at OP code, he does not use "x"!
@AshishRanjan It should be pointed out to a newbie that he does need the 'for' loop.
|
0

See if this helps you understand what you are doing:

import numpy as np

a = np.array([1,2,3,4])
print(a)

old_a = a

for x in range(0,1):
    new_a = old_a
    new_a[0] = old_a[1]
    print  new_a
    new_a[1] = old_a[2]
    print  new_a
    new_a[2] = old_a[3]
    print  new_a
    new_a[3] = old_a[0]
    print(new_a)

[1 2 3 4]
[2 2 3 4]
[2 3 3 4]
[2 3 4 4]
[2 3 4 2]

So when you do this new_a[3] = old_a[0], position O is already "2". Below gives you what you expected.

for x in range(0,1):
    new_a = old_a.copy()
    new_a[0] = old_a[1]
    print  new_a
    new_a[1] = old_a[2]
    print  new_a
    new_a[2] = old_a[3]
    print  new_a
    new_a[3] = old_a[0]
    print(new_a)

[1 2 3 4]
[2 2 3 4]
[2 3 3 4]
[2 3 4 4]
[2 3 4 1]

The fastest way to do this is 'fancy' indexing :

a     = np.array([1,2,3,4])
new_a = a[np.array([1,2,3,0])]
print new_a

array([2, 3, 4, 1])

2 Comments

I will post below
Of course, will do but I dont have the 15 reputation yet to make it public. Thanks again

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.