问题
I am making a simple definition to return a list of colors based on some intervals. Unfortunately I keep getting the following error:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
I have seen the following discussion on stackoverflow but only had failed attempts to make it work.
Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()
This is my code:
y = 5
std = pd.Series([1,1,1,1])
values = pd.Series([2, 4, 6, 8])
colors = []
def colorbybar():
for i in values:
if y < (values - (2*std)):
colors[i] = 'darkblue'
elif y < (values - std):
colors[i] = 'blue'
elif y < values:
colors[i] = 'white'
elif y < (values + std):
colors[i] = 'red'
elif y < (values + (2*std)):
colors[i] = 'darkred'
return colors
colorbybar()
回答1:
When you do y < (values - std)
it will return pd.Series
>>> y < (values - std)
0 False
1 False
2 False
3 True
dtype: bool
but here you need scalar bool
for condition so as said in error use
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
like
>>> (y < (values - std)).all()
False
>>> # or
>>> (y < (values - std)).any()
True
Thus your function would be
def colorbybar():
for i in values:
if (y < (values - (2*std))).all():
colors[i] = 'darkblue'
elif (y < (values - std)).all():
colors[i] = 'blue'
elif (y < values).all():
colors[i] = 'white'
elif (y < (values + std)).all():
colors[i] = 'red'
elif (y < (values + (2*std))).all():
colors[i] = 'darkred'
return colors
回答2:
I guess you haven’t fully understood how Python’s for works. It does not introduce any index (like in most other languages) but iterates over the members (like foreach
in most languages).
In your loop, you are trying to do arithmetic operations on values
, i.e. the whole Series, as Dishin demonstrated. You probably wanted to operate on the items of values
. You called it i
but let me choose the name value
to express what it does:
for value in values:
if y < (value - (2*std)):
# and so on
The same applies to std
which is a sequence, too. The easiest way to iterate two sequences at once seems to be zip()
:
for value, std_item in zip(values, std):
if y < (value - (2*std_item)):
Another problem is that you are trying to use i
as indices (keys) of the list colors
. This is not possible with a list. You could use a dictionary to set keys in such a way but that’s probably not what you wanted according to your description (see an archived version of the original question):
I am trying to make a definition that returns a list of colors based on whether a value is between some interval. Therefore, if y was -1 it should return the list [darkblue, darkblue, darkblue, darkblue], but if y was 11 it should return the list [darkred, darkred, darkred, darkred].
Instead of the wrong syntax colors[i]
, you could use colors.append('darkblue')
etc.
And by the way, what to do if an item in values
exceeds all the limits? Shouldn’t there be a color, too?
This is the result:
y = 5
std = pd.Series([1,1,1,1])
values = pd.Series([2, 4, 6, 8])
colors = []
def colorbybar():
for value, std_item in zip(values, std):
if y < (value - (2*std_item)):
colors.append('darkblue')
elif y < (value - std_item):
colors.append('blue')
elif y < value:
colors.append('white')
elif y < (value + std_item):
colors.append('red')
elif y < (value + (2*std_item)):
colors.append('darkred')
else: # added myself
colors.append('black')
return colors
colorbybar()
And as stark pointed out, there are more things to do with your function (def
). As it’s currently written, it would only work once as expected. When you called it again, it would reuse existing global variables, including colors
. In your case, y
, std
, and values
should be parameters and colors
a local variable that is returned at the end. This way your function will be easily reusable.
def colorbybar(y, std, values):
colors = []
for value, std_item in zip(values, std):
if y < (value - (2*std_item)):
colors.append('darkblue')
elif y < (value - std_item):
colors.append('blue')
elif y < value:
colors.append('white')
elif y < (value + std_item):
colors.append('red')
elif y < (value + (2*std_item)):
colors.append('darkred')
else: # added myself
colors.append('black')
return colors
colorbybar(5, pd.Series([1,1,1,1]), pd.Series([2, 4, 6, 8]))
来源:https://stackoverflow.com/questions/61729765/value-error-for-simple-definition-to-generate-list-of-colors