value error for simple definition to generate list of colors

时光总嘲笑我的痴心妄想 提交于 2020-05-17 05:51:03

问题


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

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