Customize bar colour depends on condition

Hi,

I’m trying to add a dataframe that is in the below format as a barchart.

ticker	value	bar_colour

0 NZDCAD -4.25 Green
1 AUDCAD -3.96 Red
2 EURCAD -2.86 Green
3 GBPCHF -2.49 Black
etc

I’m trying to update the figure via a callback. and the code I currently have is. Essentially I’m trying to loop through each data point and create its own barchart, then combining them. It looks quite inelegant but it is the solution proposed by this thread “Different colors for bars in barchart by their value

fig = make_subplots(rows=1, cols=1)

for index, label_df in df.iterrows():
    trace = go.Bar(x=[label_df['ticker']],
                       y=[label_df['value']],
                       marker={'color': label_df['bar_colour']})
    fig.add_trace(trace, row=1, col=1,secondary_y=False)

return fig

The chart however is empty, with the y axis looks very funny and I think is somehow is the problem.

So my question is two part

  1. Is there an easier way to achieve my goal?
  2. Why isn’t my code working?

Thanks very much

Felton

Your code is not working because you need to remove the external [] in x and y.

For a simpler way, you can just set marker_color to a column as follows (in this case you have a single trace):

import plotly.express as px
df = px.data.gapminder().query("year == 2007").query("continent=='Europe'")
df['color'] = 'red'
df['color'][5:10] = 'black'

import plotly.graph_objects as go
fig = go.Figure(
    go.Bar(x=df['country'],
                y=df['gdpPercap'],
                marker={'color': df['color']})
)
fig.show()

You can also use plotly.express to perform a groupby by color, and create a trace per color. This will order the bars by color

import plotly.express as px
df = px.data.gapminder().query("year == 2007").query("continent=='Europe'")
df['color'] = 'red'
df['color'][5:10] = 'black'

fig = px.bar(df, x='country', y='gdpPercap', color='color', color_discrete_sequence=df.color.unique())
fig.show()

1 Like

Thanks very much. I’ve managed to make it work. You are right, I didn’t need the for loop in my case.

Thanks @Emmanuelle .