The Dude
The Dude

Reputation: 59

Plotly express, how to use for_each_trace

Can anyone help me with this issue. I am trying to color all the negative bars in my px.bar graph after it has been ploted. I am running into how to access the y value of each individual bar, I am plotting everything green and I want to go back and color the neg bars red. The dates must stay in order. Here is what I am trying

here is my dataframe

     DATE  Profit/Loss Marker  Cumulative_PnL  Daily_Volume  WinRate 
 08/16/21     -58.1995    red        -58.1995      604.0000  80.0000         
 08/17/21      -4.7700    red        -62.9695        4.0000  50.0000        
 08/18/21      31.4984  green        -31.4711     1908.0000 100.0000      
 08/20/21      49.6200  green         18.1489     1006.0000  50.0000       
 08/23/21    -930.1800    red       -912.0311      712.0000  50.0000        
 08/24/21      99.1000  green       -812.9311      306.0000 100.0000         
 08/25/21      -0.6400    red       -813.5711      332.0000  60.0000        
 08/26/21     -50.0300    red       -863.6011     2556.0000  66.6667        
 08/27/21      -9.9100    red       -873.5111       38.0000  81.8182         
 08/30/21       7.8500  green       -865.6611      424.0000  91.6667        
 08/31/21       1.0000  green       -864.6611       40.0000 100.0000      
 09/01/21    -367.9500    red      -1232.6111      981.0000  76.9231         
 09/02/21     178.9900  green      -1053.6211      308.0000  71.4286        
 09/03/21     -32.1000    red      -1085.7211      928.0000  62.5000

fig1.for_each_trace(lambda trace: trace.update(marker_color= 'red') if trace.y < 0 else (),) 

enter image description here

Upvotes: 2

Views: 3201

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31146

  • you have not provided sample data for all traces, so I've generated a data frame
  • post straight forward call to px.bar() I loop through the traces, setting +ve Y values to black and using assigned color when bars were created
  • key is then updating trace in figure with required change
import plotly.express as px
import pandas as pd
import numpy as np

ROWS = 20
LINES = 5

# construct a dataset to use plotly express with multiple traces
df = (
    pd.wide_to_long(
        pd.DataFrame(
            np.random.uniform(-10, 3, (ROWS, LINES)),
            columns=[f"Y{n}" for n in range(LINES)],
        ).reset_index(),
        i="index",
        j="color",
        stubnames="Y",
    )
    .reset_index()
    .assign(color=lambda d: d["color"].astype(str))
)

fig = px.bar(df, x="index", y="Y", color="color", barmode="group")

# in each trace, set all positive numbers to black and negative numbers use trace color
for t in fig.data:
    fig.update_traces(marker={"color": np.where(t.y>0, "black", t.marker.color)}, selector={"name":t.name})

fig.show()

enter image description here

Upvotes: 3

Related Questions