Creating a Row-Wise Stacked Bar Chart

Hello all!

Getting used to using Python’s implementation of Plotly after previously using a Google Charts wrapper for my data visualizations. I’m trying to create a stacked bar chart using revenue data for a multitude of products, in an effort to show the revenue impact of each product as it relates to the sum total of revenue. The data follows this format:

**Product**            **Revenue**
Gizmos                       100000
Gadgets                      200000
Whirligigs                   125000

So the stacked bar chart should be a single bar showing the total revenue (425,000 for the example), comprised of three chunks stacked on one another (corresponding to Gizmos, Gadgets, and Whirligigs). Ideally, I’d like to add in a horizontal line representing this Quarter’s target revenue, as well - I know how to do that with standard bar charts, but I’m not 100% sure it’s supported with stacked bar charts.

The issue I’ve run into is that the standard implementation of stacked bar charts in Plotly seems to assume that each column is a new stack, when my data is arranged row-wise, and each new chunk of the stack is created using

go.Bar(
    x=df['x'], # assign x as the dataframe column 'x'
    y=df['y']
)

where y is the set of values for that chunk.

Is the answer here to transpose the data, such that it fits the following format:

**Quarter**            **Gizmos**            **Gadgets**            **Whirligigs**
Q1                       100000                200000                   125000
Q2                            0                     0                        0                
Q3                            0                     0                        0        

And then write a loop for the go.Bar() portion creating a trace for each product in sequence? I could theoretically do that, but it would be a bit annoying and potentially problematic since the number of products we have isn’t set in stone. Is there already a solution to creating row-wise stacked bar charts?

There are a couple of ways you can go about this without having to transpose your data. Since your data is already tidy, it should work with plotly express.

import plotly_express as px
import pandas as pd

df = pd.DataFrame(dict(revenue=[2000,3000,4000], products=['A', 'B', 'C'], quarter=['Q1', 'Q1', 'Q1']))

fig = px.bar(df, x='quarter', y='revenue', color='products')

or you can do the same thing without plotly express by using a loop/list comprehension over the unique products in your dataframe.

import plotly.graph_objs as go

fig = go.Figure([
    go.Bar(x=df[df.products == product].quarter,
           y=df[df.products == product].revenue,
           name=product
          )
    for product in df.products.unique()]).update(layout_barmode='stack')

Both of these methods generate a plotly figure object which you can modify with fig.update() to add a line as well.

fig.update(layout_shapes = [{
            'type': 'line',
            'x0': 0,
            'y0': 9500,
            'xref': 'paper',
            'x1': 5,
            'y1': 9500,
            'line': {
                'width': 4,
            }
        }]
)