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

和自甴很熟 提交于 2019-12-22 11:24:14

问题


although I know there's various questions looking for solutions to this error message, I've yet to find an answer that helps me solve my code to get the comparison working, I have the code

def f(x,d,h,L):
    ans=0.
    if ((0.<=x) & (x<d)):
        ans=h*(x/d)
    elif ((d<=x) & (x<=L)):
        ans=((L-x)/(L-d))
    return ans

x=np.linspace(0,10,1000)
h=5*10**(-3)
d=16*10**(-2)
L=64.52*10**(-2)
func=f(x,d,h,L)

But when I try running it I get an error pointing to the if line with the error code in the title, I've tried the proposed solutions given in similar questions such as using np.logical_and or and instead of & but all three yield the same error, please help me out


回答1:


Use numpy.where. Optionally, use exponential notation for floating point numbers.

import numpy as np

def f(x, d, h, L):
    return np.where(x < d, h*(x/d), (L - x)/(L - d))

x = np.linspace(0,10,1000)
h = 5e-3
d = 16e-2
L = 64.52e-2

func = f(x, d, h, L)



回答2:


You're focusing on the conjunction of the clauses, but it's the clauses themselves. You probably want here something like:

if numpy.all(0 <= x) and numpy.all(x < d):
    ...

See the docs for numpy.all.




回答3:


I was able to solve my problem by defining x as an array an creating a cycle for evaluating every x individually, not sure if it's the most efficient way of doing it but I'm only working with 1000 iterations so it works well, here's what I did:

def f(a,d,h,L):
ans2=[]
for i in range(1000):
    if (0.<=a[i]) & (a[i]<d):
        ans=x[i]*(h/d)
        ans2.append(ans)
    elif ((d<=a[i]) & (a[i]<=L)):
        ans=h*((L-a[i])/(L-d))
        ans2.append(ans)
return ans2
L=64.52*10**(-2)
x=np.linspace(0,L,1000)
h=5*10**(-3)
d=16*10**(-2)
plot.plot(x,f(x,d,h,L))

Hope it solves somebody else's problem as well, and if it can be optimized to have be faster, I'd love to learn how.




回答4:


The error is related to the fact that an array contains more than value. For instance a < 0 where a = 1 has a definitive truth value (false). However, what if a is an array. eg [-1, 0, 1], some elements are less than zero and some are greater than or equal to zero. So what what should the truth value be? To be able to create a truth value you have to specify if you want all the values to be less than zero, or for at least one value to be less than zero (any value).

Since mathematical operators on numpy arrays return arrays themselves we can call all or any on those arrays to see if all or at least one value is truthful. You would rewrite your if statement as:

if (0 <= x).all() and (x < d).all():
    ...
# alternatively
if 0 <= x.min() and x.max() < d:
    ...



回答5:


Others have answered assuming that you want to apply one calculation or other depending on whether all/any values of x meet the respective conditions. I'll make a different assumption - that you want to apply f to each element of x individually.

Applied element by element I get:

In [226]: x=np.linspace(0,1,20)

In [227]: [f(z,d,h,L) for z in x]
Out[227]: 
[0.0,
 0.0016447368421052631,
 0.0032894736842105261,
 0.0049342105263157892,
 0.89586497157981526,
 0.78739098364212268,
 0.6789169957044302,
 0.57044300776673762,
 0.46196901982904509,
 0.35349503189135251,
 0.24502104395365998,
 0.13654705601596731,
 0.028073068078274897,
 0.0,
 0.0,
 0.0,
 0.0,
 0.0,
 0.0,
 0.0]

The vectorized equivalent:

In [238]: I = (0<=x) & (x<d)
In [239]: J=(d<=x) & (x<=L)

In [240]: out=np.zeros_like(x)
In [241]: out[I]=h*(x[I]/d)
In [242]: out[J]=(L-x[J])/(L-d)

In [243]: out
Out[243]: 
array([ 0.        ,  0.00164474,  0.00328947,  0.00493421,  0.89586497,
        0.78739098,  0.678917  ,  0.57044301,  0.46196902,  0.35349503,
        0.24502104,  0.13654706,  0.02807307,  0.        ,  0.        ,
        0.        ,  0.        ,  0.        ,  0.        ,  0.        ])

I'll let you package that as a function.


With the parameters as given (including the full x), np.all(I) and np.all(J) both are False, meaning f would return 0.0 if applied to x as a whole.


def f(x, d, h, L):
   I = (0<=x) & (x<d)
   J=(d<=x) & (x<=L)
   out=np.zeros_like(x)
   out[I]=h*(x[I]/d)
   out[J]=(L-x[J])/(L-d)
   return out



回答6:


def f(x,d,h,L):
    ans=0.
    if ((0.<=x) & (x<d)):
        ans=h*(x/d)
    elif ((d<=x) & (x<=L)):
        ans=((L-x)/(L-d))
    return ans

#A ajouter
f_vec = numpy.vectorize(f)
#et c'est tout^^

x=np.linspace(0,10,1000)
h=5*10**(-3)
d=16*10**(-2)
L=64.52*10**(-2)
func=f_vec(x,d,h,L) #ici il faut tout de même ajouter _vec


来源:https://stackoverflow.com/questions/31126893/the-truth-value-of-an-array-with-more-than-one-element-is-ambiguous-use-a-any

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!