0

I'm using advanced indexing on the numpy arrays but find that my columns do not swap but instead they're replaced.

For example:

test_array = np.array([ [1, 2, 3, 4, 5] , [5, 4, 3, 2, 1] , [5, 2, 2, 2, 1] , [1, 2, 2, 1, 1] ])
zeros = np.repeat( np.zeros((1, 5)) , 2, axis=0)
swap_array = np.vstack([test_array, zeros])

swap_array[ : , [ 0 , 2 ] ] = swap_array[ : , [ -2 , -1 ] ]
print(swap_array)

#
[[0. 0. 5. 1. 0. 0.]
 [0. 0. 2. 2. 0. 0.]
 [0. 0. 2. 2. 0. 0.]
 [0. 0. 2. 1. 0. 0.]
 [0. 0. 1. 1. 0. 0.]]

What is the most effective way to swap the first-two columns with the last two, given I do not know the same of the array.

tesla john
  • 310
  • 1
  • 2
  • 9
  • This certainly answers your question: [Swap two values in a numpy array.](https://stackoverflow.com/questions/22847410/swap-two-values-in-a-numpy-array) – Jérôme Richard Nov 20 '22 at 11:06
  • @JérômeRichard No, that wants to swap values and I have not having issues with swapping in general. I just find when trying to index with `-` instead of swapping, it replaces. – tesla john Nov 20 '22 at 11:07
  • Ha Ok Indeed. I turns out this applies to the current answer though. – Jérôme Richard Nov 20 '22 at 11:10

1 Answers1

1

They are indeed replaced, because there is no assignment stating that the last two columns should contain the first two. To do this, you can use the comma operator (or tuple unpacking), which evaluates all expressions on the right-hand side, before any assignment is made. There are pitfalls with this approach, so it is not safe, in general (See comments below & thanks @Jérôme Richard).

test_array = np.array([ [1, 2, 3, 4, 5] , [5, 4, 3, 2, 1] , [5, 2, 2, 2, 1] , [1, 2, 2, 1, 1] ])
zeros = np.repeat( np.zeros((1, 5)) , 2, axis=0)
swap_array = np.vstack([test_array, zeros])
print(swap_array)

swap_array[ : , [ 0 , 2 ] ], swap_array[ : , [ -2, -1 ] ] = swap_array[ : , [ -2 , -1 ] ], swap_array[ : , [ 0 , 2 ] ]
print(swap_array)

You can do this more concisely and safely. The approach below should be preferred.

swap_array[ : , [ 0 , 2, -2, -1 ] ] = swap_array[ : , [ -2 , -1, 0, 2 ] ]

Result for both codes:

[[1. 2. 3. 4. 5.]
 [5. 4. 3. 2. 1.]
 [5. 2. 2. 2. 1.]
 [1. 2. 2. 1. 1.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]

[[4. 2. 5. 1. 3.]
 [2. 4. 1. 5. 3.]
 [2. 2. 1. 5. 2.]
 [1. 2. 1. 1. 2.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]
Alex P
  • 1,105
  • 6
  • 18
  • 1
    The concise example is actually also more correct. Otherwise, there is certainly an issue with the views (see the comment in the second answer in the link in the OP question). – Jérôme Richard Nov 20 '22 at 11:11
  • 1
    @JérômeRichard indeed, you are right. I'll edit the post to make this clear – Alex P Nov 20 '22 at 11:16
  • What if I have a list of numpy arrays and wanted to change the positions for each array. What des this look like? – tesla john Nov 20 '22 at 12:17
  • @teslajohn If you have multiple arrays and want to perform the above swap on all of them, you can loop over the list of the arrays an use the iterator with the code above. e.g. `for a in list_of_arrays: a[:, [0, 2, -2, -1]] = a[:, [-2, -1, 0, 2]]` – Alex P Nov 20 '22 at 12:20