简体   繁体   中英

add alpha (shade) to plotly express stacked bar

I have the following pandas dataframe

import pandas as pd
df_dict = {'index': [0, 1, 2, 3, 4, 5, 6, 7, 8], 'columns': ['from', 'moving', 'N', 'total', 'perc', 'helper', 'label'], 'data': [['0', 'no', 29, 39, 74.35897435897436, 'all', '74.4 %'], ['0', 'yes', 10, 39, 25.641025641025642, 'all', '25.6 %'], ['1', 'no', 77, 84, 91.66666666666667, 'all', '91.7 %'], ['1', 'yes', 7, 84, 8.333333333333334, 'all', '8.3 %'], ['2', 'no', 6, 6, 100.0, 'all', '100.0 %'], ['3', 'no', 19, 25, 76.0, 'all', '76.0 %'], ['3', 'yes', 6, 25, 24.0, 'all', '24.0 %'], ['4', 'no', 30, 45, 66.66666666666667, 'all', '66.7 %'], ['4', 'yes', 15, 45, 33.333333333333336, 'all', '33.3 %']]}

df = pd.DataFrame(index=df_dict['index'], columns=df_dict['columns'], data=df_dict['data'])

I am using the following code:

import plotly.express as px

def pl(dt, color_col, title, facet_col=None,
           color_discrete_map=dict(zip(['4', '0', '2', '3', '1'],['#003898', '#164461','#61B3C1', '#8ED3F6 ','#8DD1C8']))):

           px.bar(dt, x='helper', y='perc', color=color_col, facet_col=facet_col, category_orders={col: sorted(dt_temp[col].unique())},
           color_discrete_map=color_discrete_map, title=title, text='label').show()

pl(dt=df, facet_col='from',
                         color_col='from', title='title')

In order to produce this plot:

在此处输入图像描述

I would like to add a shading of the specified color in the color_discrete_map with respect to the moving column of the df , so that the no 's are a bit more faded.

How could I do that with plotly express?

I don't believe that you can access the text font through any of the px.bar parameters. However, you can save your px.bar in an object called fig , then directly modify the each bar object through fig.data[0] , fig.data[1] , ... fig.data[n-1] for n bars.

The text color for each of these bars can be modified by passing a dictionary to the textcolor attribute of each of bar objects fig.data[0]... fig.data[n-1] . For example, you could modify the text of the first bar to be red with the line: fig.data[0].textcolor: {'color': 'red'} . This lends itself to looping through each fig.data bar object and modifying the textcolor attribute to be the desired color.

The last part is to make your color a shade of the bar color. I am not that familiar with hex color codes, so it makes the most sense to convert each hex color code to an rgb tuple of three values, and find the intermediate color between this value and white. plotly.colors conveniently has the methods hex_to_rgb and find_intermediate_color so we can use these to convert each of your hex colors to rgb, then find the rgb tuple between that color and white which is rgb(255,255,255) .

To be consistent with the way you've structured your program, I put the code setting the textfont attributes in your pl function.

import pandas as pd
import plotly.express as px

from plotly.colors import hex_to_rgb, find_intermediate_color

df_dict = {'index': [0, 1, 2, 3, 4, 5, 6, 7, 8], 'columns': ['from', 'moving', 'N', 'total', 'perc', 'helper', 'label'], 'data': [['0', 'no', 29, 39, 74.35897435897436, 'all', '74.4 %'], ['0', 'yes', 10, 39, 25.641025641025642, 'all', '25.6 %'], ['1', 'no', 77, 84, 91.66666666666667, 'all', '91.7 %'], ['1', 'yes', 7, 84, 8.333333333333334, 'all', '8.3 %'], ['2', 'no', 6, 6, 100.0, 'all', '100.0 %'], ['3', 'no', 19, 25, 76.0, 'all', '76.0 %'], ['3', 'yes', 6, 25, 24.0, 'all', '24.0 %'], ['4', 'no', 30, 45, 66.66666666666667, 'all', '66.7 %'], ['4', 'yes', 15, 45, 33.333333333333336, 'all', '33.3 %']]}

df = pd.DataFrame(index=df_dict['index'], columns=df_dict['columns'], data=df_dict['data'])
bar_color_map = dict(zip(['4', '0', '2', '3', '1'],['#003898', '#164461','#61B3C1', '#8ED3F6','#8DD1C8']))

def pl(dt, color_col, title, facet_col=None, color_discrete_map=bar_color_map):
    fig = px.bar(dt, x='helper', y='perc', color=color_col, facet_col=facet_col, 
        # category_orders={col: sorted(dt_temp[col].unique())},
        category_orders={color_col: sorted(dt[color_col].unique())},
        color_discrete_map=color_discrete_map, title=title, text='label')

    ## set fig.data.textfont attribute
    for bar_number in range(len(fig.data)):
        bar_color = hex_to_rgb(bar_color_map[str(bar_number)])
        shaded_text_color = find_intermediate_color(bar_color,(255,255,255),0.5)
        shaded_int_rgb_color = tuple([int(text_color) for text_color in shaded_text_color])
        # print('rgb'+str(shaded_int_rgb_color))
        fig.data[bar_number].textfont = {'color': 'rgb'+str(shaded_int_rgb_color)}
    fig.show()

pl(dt=df, facet_col='from', color_col='from', title='title')

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM