Search code examples
pythonplotlyplotly-dashplotly-python

Stacked bar chart with dual axis in Plotly


Please consider the example below:

import pandas as pd

mydata = pd.DataFrame({'time': [pd.to_datetime('2021-01-02'),
                               pd.to_datetime('2021-01-02'),
                               pd.to_datetime('2021-01-03'),
                               pd.to_datetime('2021-01-03')],
                      'group': ['a','b','a','b'],
                      'value': [1,3,3,5]})

myline = pd.DataFrame({'time': [pd.to_datetime('2021-01-02'),
                                 pd.to_datetime('2021-01-03')],
                       'value':[39,46]})

mydata
Out[222]: 
        time group  value
0 2021-01-02  a     1    
1 2021-01-02  b     3    
2 2021-01-03  a     3    
3 2021-01-03  b     5    

I am trying to create a dual axis chart with the line in myline on one axis and the stacked bar charts from mydata on another.

My code below almost achieves that, but there are few issues:

  1. The bars are not stacked !
  2. Because my data has many different categories, I need to use a colorscale with many different colors like dark24 (https://plotly.com/python/discrete-color/). How can I specify that for the fill color of the bars?

Any suggestion greatly appreciated. Thanks!

enter image description here

import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig = make_subplots(specs=[[{"secondary_y": True}]])

fig.add_trace(
    go.Scatter(x=myline['time'], 
               y=myline["value"], 
               name="Column1", 
               mode="lines"),
    secondary_y=True
)

layout = go.Layout(barmode='stack')

for t in mydata['group'].unique():
    dfp = mydata.loc[mydata['group']==t]
    fig.add_trace(go.Bar(x=dfp['time'], 
                          y = dfp['value'], 
                          name=t,
                          text = t),
                  secondary_y=False)

fig.update_xaxes(title_text="Letter")

# Set y-axes titles
fig.update_yaxes(title_text="Column2", secondary_y=False)
fig.update_yaxes(title_text="Column1", secondary_y=True)
fig.update(layout_showlegend=False)
fig.show()

Solution

  • The stacked graph is set, but it was not enabled, so I changed the bar graph mode to stacked along with hiding the legend. Also, I couldn't find a colormap setting in graph_objects, so I updated the default colormap with the desired colormap. I checked the test data with three objects, and they are updated with the new color map. However, I did not go as far as to check the 24 colors, so you will have to check it yourself.

    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    import plotly.express as px
    
    colors = px.colors.qualitative.Dark24
    
    fig = make_subplots(specs=[[{"secondary_y": True}]])
    
    fig.add_trace(
        go.Scatter(x=myline['time'], 
                   y=myline["value"], 
                   name="Column1", 
                   mode="lines"),
        secondary_y=True
    )
    
    #layout = go.Layout(barmode='stack')
    
    for t in mydata['group'].unique():
        dfp = mydata.loc[mydata['group']==t]
        fig.add_trace(go.Bar(x=dfp['time'], 
                              y = dfp['value'], 
                              name=t,
                              text = t),
                      secondary_y=False)
    
    fig.update_xaxes(title_text="Letter")
    
    # Set y-axes titles
    fig.update_yaxes(title_text="Column2", secondary_y=False)
    fig.update_yaxes(title_text="Column1", secondary_y=True)
    fig.update_layout(showlegend=False, barmode='stack')
    
    fig.layout.colorway = colors
    fig.show()
    

    enter image description here