How to set multiple conditions for color in Altair 5.5 using alt.when().then().otherwise()? - Stack Overflow

How can I set multiple conditions for colours of a bar chart? Specifically, I want the color scheme for

How can I set multiple conditions for colours of a bar chart? Specifically, I want the color scheme for values < 0 to be "reds", values > 0 to "lightgray" and the "Gold" name to be "goldenrod" color. I am using Altair 5.5.

Here is what I have tried:

np.random.seed(1)
test = pd.DataFrame(
    {
        'Name': ['Cat_A', 'Cat_B', 'Cat_C', 'Cat_D', 'Gold'],
        'Value': np.random.randint(-10,10,5),
    },
).sort_values(by='Value', ascending=False).reset_index(drop=True).reset_index()
test.rename(columns={'index': 'Rank'}, inplace=True)

color = (
    alt.when(alt.datum.Value < 0)           # check if Value < 0
    .then(alt.Color("Rank:O").scale(scheme='reds').legend(None)) # then 'reds'
    #.when(alt.datum.Name == 'Gold')        # check if Name is 'Gold'
    #.then(alt.value('goldenrod'))          # If true, use 'goldenrod'
    .otherwise(alt.value('lightgray'))      # Default color if neither is true
)
alt.Chart(test).mark_bar(tooltip=True).encode(
    x=alt.X('Value:Q').title('Change in Score'),
    y=alt.Y('Name:N', sort=test['Name'].to_list()).title(None),
    color=color
)

I can only get two conditions to work, and not the "goldenrod" color (which I have commented out above in order to get this):

How can I set multiple conditions for colours of a bar chart? Specifically, I want the color scheme for values < 0 to be "reds", values > 0 to "lightgray" and the "Gold" name to be "goldenrod" color. I am using Altair 5.5.

Here is what I have tried:

np.random.seed(1)
test = pd.DataFrame(
    {
        'Name': ['Cat_A', 'Cat_B', 'Cat_C', 'Cat_D', 'Gold'],
        'Value': np.random.randint(-10,10,5),
    },
).sort_values(by='Value', ascending=False).reset_index(drop=True).reset_index()
test.rename(columns={'index': 'Rank'}, inplace=True)

color = (
    alt.when(alt.datum.Value < 0)           # check if Value < 0
    .then(alt.Color("Rank:O").scale(scheme='reds').legend(None)) # then 'reds'
    #.when(alt.datum.Name == 'Gold')        # check if Name is 'Gold'
    #.then(alt.value('goldenrod'))          # If true, use 'goldenrod'
    .otherwise(alt.value('lightgray'))      # Default color if neither is true
)
alt.Chart(test).mark_bar(tooltip=True).encode(
    x=alt.X('Value:Q').title('Change in Score'),
    y=alt.Y('Name:N', sort=test['Name'].to_list()).title(None),
    color=color
)

I can only get two conditions to work, and not the "goldenrod" color (which I have commented out above in order to get this):

Share Improve this question asked Feb 21 at 4:44 footfalconfootfalcon 6417 silver badges18 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I believe the basic usage of chaining when().then() multiple times is that it implies a priority: i.e. the FIRST when() that is true will take effect.

In the example shown here, "Gold" has a value < 0, and therefore (were it not commented) it would still trigger the first when() and be colored with the Reds scale, and this plot would look the same as it does now.

On the other hand, if name=="Gold" was the first when().then(), I think you would get the result you want.

-- UPDATE --

I'm just coming back to Altair ver 5+, and it seems the new when().then() syntax does not like mixing in alt.Color() encodings, and returns an error for me "TypeError: Chained conditions cannot be mixed with field conditions."

So instead, here's an old school hacky way of doing it. Still works, I tested it this time:

condition1 = alt.condition(alt.datum.Name == 'Gold', alt.value('goldenrod'), alt.Color("Rank:O").scale(scheme='reds').legend(None))
condition2 = alt.condition(alt.datum.Value >= 0, alt.value('lightgray'), alt.Color("Rank:O").scale(scheme='reds').legend(None))
combined_condition = condition1.copy()
combined_condition['condition'] = [condition1['condition'], condition2['condition']]


alt.Chart(test).mark_bar(tooltip=True).encode(
    x=alt.X('Value:Q').title('Change in Score'),
    y=alt.Y('Name:N', sort=test['Name'].to_list()).title(None),
    color=combined_condition
)

Is cobbling together two alt.condition()s elegant? Nope, but I hope this helps. It might break with small variations because I don't know if this hack is intended, but it works for this example.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745166960a4614690.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信