问题
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