1
>>> a = 0.001 * np.random.randint(0, 1000, size=(5))
>>> a
array([0.524, 0.311, 0.603, 0.957, 0.923])

>>> b = np.random.randint(0, 2, size=(3, 5))
>>> b
array([[1, 1, 1, 0, 1],
       [0, 0, 1, 0, 0],
       [0, 0, 1, 0, 1]])

I want to map over each row of the 2D array b, and if the value at row[i] == 1, set it to a[i], if the value at row[i] == 0, I want to set it to 1 - a[i].

For example, for b[1] = row = [0, 0, 1, 0, 0], it should become:

[1 - 0.524, 1 - 0.311, 0.603, 1 - 0.957, 1 - 0.923]

i.e.

[0.476, 0.689, 0.603, 0.043, 0.077]

How can I achieve this for all rows of the 2D matrix without resorting to for loops? (i.e. leverage efficiency of numpy)

2
  • What's the shape of the result supposed to be? Show the full working iterative code. Commented Jul 4, 2022 at 2:43
  • np.where(b.astype(bool), 1 - a, a) Commented Jul 4, 2022 at 3:18

1 Answer 1

1

There are a couple of ways of doing this. I would probably use the where and out arguments to np.subtract:

np.subtract(np.ones(len(b)), a, out=np.broadcast_to(a, b.shape).copy(), where=b.astype(bool))

Going with @hpaulj's solution to use the 3-arg version of np.where is probably much cleaner in this case:

np.where(b, a, 1 - a)
Sign up to request clarification or add additional context in comments.

4 Comments

When I do this, I get non-broadcastable output operand with shape (5,) doesn't match the broadcast shape (3,5) as an error, unfortunately, is there any way to perform it on a 2D array?
The out needs to be (3,5) the shape of b. For example a[None].repeat(3, axis=0)
Here the np.where function is a cleaner solution.
@herophant. Sorry, I forgot to broadcast the ones correctly.

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.