1

Let's say I have a 3x3 numpy array:

[[0, 1, 2],
 [2, 0, 1],
 [1, 2, 0]]

And an additional vector:

[2,
 1,
 1]

For each row in the matrix, I want to swap the number at the 0th index with the number at the corresponding index from the vector. In this example, after the swap, the final output would be:

[[2, 1, 0], # the 0th and 2nd positions have been swapped
 [0, 2, 1], # the 0th and 1st positions have been swapped
 [2, 1, 0]] # the 0th and 1st positions have been swapped

How can you do this?

1
  • x[[0, 1, 2], [2, 1, 1]], x[[0, 1, 2], [0, 0, 0]] = x[[0, 1, 2], [0, 0, 0]], x[[0, 1, 2], [2, 1, 1]] Commented Sep 17, 2018 at 1:16

2 Answers 2

1
import numpy as np

A = np.asarray([[0, 1, 2],
                [2, 0, 1],
                [1, 2, 0]])

col_idxs = np.asarray([2, 1, 1])
row_idxs = np.arange(len(A))
a = A[:, 0].copy()
A[:, 0] = A[row_idxs, col_idxs]
A[row_idxs, col_idxs] = a

or more concisely

c = np.asarray([2, 1, 1])
r = np.arange(len(A))
A[:, 0], A[r, c] = A[r, c], A[:, 0].copy()

Here we make use of the fact that we can index individual elements of a numpy array by supplying it two separate list-like objects for the corresponding row and col indexes.

So the line A[:, 0], A[r, c] = A[r, c], A[:, 0].copy() can be read as get the indexed elements from each column and swap them with the first column.

Edit

Thanks to @Paul Panzer for his comment, the assignment can be made even shorter by writing it as A[r, c], A[:, 0] = A[:, 0], A[r, c].

Note that the order of assignment to A[r, c] and A[:, 0] has been change compared to the earlier version.

The reason the copy can be omitted here is because

  1. In an assignment, the right hand side is evaluated fully before assigning to the variables on the left.
  2. Fancy indexing of Numpy (A[r, c] here) returns a copy unlike slices (A[:, 0]) which returns a view.

Therefore, what this new line of code says is

  1. Get a view (i.e., reference) to the the first column of A
  2. Create a copy of A[r, c]. The copy is implicit because of fancy indexing of Numpy array.
  3. Assign A[r, c] the values of the first column of A using the view of that column.
  4. Assign the first column of A the copy of A[r, c] we made earlier (note that by this point A[r, c] has already been assigned the old value of A[:, 0].)

Also, we don't need to convert the indexes to Numpy array.

c = [2, 1, 1]
r = range(len(A))
A[r, c], A[:, 0] = A[:, 0], A[r, c]
Sign up to request clarification or add additional context in comments.

3 Comments

Or even shorter A[r, c], A[:, 0] = A[:, 0], A[r, c] using the fact that A[r, c] makes a copy anyway.
@PaulPanzer No. A[:, 0] returns a view as it is a slice, so the copy is necessary.
@PaulPanzer Oh yes you are correct. Ignore my previous comment. I did not see that you swap the order of assignment.
0
a= np.array([[0,1,2],[2,0,1],[1,2,0]])
b=[2,1,1]
for rc, r in enumerate(a):
    r[0], r[b[rc]] =  r[b[rc]], r[0]
print(a)

Comments

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.