0
import numpy as np


a = np.array([[3.5,6,8,2]])
b = np.array([[6,2,8,2]])
c = np.array([[2,3,7,5]])
d = np.array([[3,2,5,1]])
if a > b:
    e = 2*a+6*c
else:
    e = 3*c + 4*d

print(e)

then I got

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

and if I type in print(e), I got

[2, 3, 7, 5, 2, 3, 7, 5, 2, 3, 7, 5, 3, 2, 5, 1, 3, 2, 5, 1, 3, 2, 5, 1, 3, 2, 5, 1]

The e I want to construct is an array that has the same dimension with a,b,c,d , and the if statement that decides what equation will be used to make each element.

In other words, for the elements in of the first place of a and b: 3.5<6, so e = 3c + 4d = 32 + 43 = 18 For the second elements: 6>2, e = 2a+6c = 26 + 63 = 30

Third: 8=8, e = 3c + 4d = 37 + 45 = 41

Fourth: 2 = 2, e = 3c + 4d = 35 + 41 = 19

e = [18,30,41,19]

I tried to find someone who asked about constructing a script doing such things, but I could find none, and all numpy questions about if statement(or equivalent) did not help. Thanks.(It seems that a.all or a.any from the python recommendation did not help as well.)

5
  • Seems like a use case for np.where() Commented Jan 26, 2022 at 22:10
  • if is a one time action, not a 'for each element' iterator. Commented Jan 26, 2022 at 22:57
  • @hpaulj many people who are new to Numpy get confused because Numpy data types cause a lot of operations to "broadcast", but there is nothing Numpy can do to make the language syntax also broadcast - so it creates awkward seams. a * b multiplies elementwise; a == b compares elementwise; but the result of that elementwise comparison can't be used to do conditional work elementwise. Commented Jul 22, 2023 at 7:39
  • @KarlKnechtel, this is a clear cases where they want an element-wise application. In other cases it isn't so clear, even to the poster. The all/any suggestion isn't always helpful, but suggesting a concise element-wise fix is harder. I think the error is actually produced by (x>0).__bool__(), which is called (by the interpreter?) any time the code expects a boolean value - such as if, or. pandas and sympy have there own versions of the ambiguity error. Commented Jul 22, 2023 at 15:52
  • Yes, the error is produced by boolean conversion. There are various fixes depending on what the user is trying to do, and understanding the problem is a general topic that is well covered at the now-linked duplicate. Commented Jul 22, 2023 at 18:16

2 Answers 2

4

Use numpy.where:

Return elements chosen from x or y depending on condition.

e = np.where(a > b, 2*a+6*c, 3*c + 4*d)
Sign up to request clarification or add additional context in comments.

Comments

0
In [370]: a = np.array([[3.5,6,8,2]])
     ...: b = np.array([[6,2,8,2]])
     ...: c = np.array([[2,3,7,5]])
     ...: d = np.array([[3,2,5,1]])
     ...: 
In [371]: a.shape
Out[371]: (1, 4)
In [372]: a[0].shape
Out[372]: (4,)

The problem with the if is that a>b is an array. There's no one True/False value to "switch" on:

In [373]: a>b
Out[373]: array([[False,  True, False, False]])

where does the array "switch"; an equivalent way is:

In [376]: mask = a>b
In [377]: e = 3*c + 4*d
In [378]: e
Out[378]: array([[18, 17, 41, 19]])
In [379]: e[mask] = 2*a[mask] + 6*c[mask]
In [380]: e
Out[380]: array([[18, 30, 41, 19]])

np.where itself does not iterate (many pandas users seem assume it does). It works with the whole arrays, the condition array (my mask) and the whole array values.

To use the if, we have to work with scalar values, not arrays. Wrap the if/else in a loop. For example:

In [381]: alist = []
In [382]: for i,j,k,l in zip(a[0],b[0],c[0],d[0]):
     ...:     if i>j:
     ...:         f = 2*i+6*k
     ...:     else:
     ...:         f = 3*k+4*l
     ...:     alist.append(f)
     ...: 
In [383]: alist
Out[383]: [18, 30.0, 41, 19]

This works because i and j are single numbers, not arrays.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.