6
votes

Is it possible to have two stacked bar charts side by side each of them coming from a single column?

Here's my df:

Field       Issue

Police      Budget cuts
Research    Budget cuts
Police      Time consuming
Banking     Lack of support
Healthcare  Lack of support
Research    Bureaucracy
Healthcare  Bureaucracy
Banking     Budget cuts

I want a stacked bar chart of Field next to a stacked bar chart of issues by field.

Thanks guys!

1

1 Answers

6
votes

For an example on how to make a stacked bar chart with the specific dataset provided, take a look at the suggestion in Plotly-Dash: Want two stacked bar charts side by side from single df column. The following answer addresses how you can not make a stacked bar chart with a single trace. To show you why, I'll start with what may seem like redundant details. But hopefully everything will be clear in the end.


In plotly terms, trace is used to describe a graph object such as Scatter or Bar like in the snippet below.

Snippet 1.1:

import plotly.graph_objs as go
fig = go.Figure(go.Bar(x=['CategoryA', 'CategoryB', 'CategoryC'],
                       y=[20, 14, 23]))
fig.update_layout(template = 'plotly_dark').show()

If you look at the snippet above, you'll see that that is a bar chart with a single trace in the form of go.Bar(x=['CategoryA',....

Plot 1.1:

enter image description here

Now, how can we add something to make it a stacked chart? If you start out by adding an element to x like 'CategoryD', then nothing happens. And that's a bit interesting since you'd might expect an error message instead.

Plot 1.2: Added x value

enter image description here

Snippet 1.2

import plotly.graph_objs as go
fig = go.Figure(go.Bar(x=['CategoryA', 'CategoryB', 'CategoryC', 'CategoryD'],
                       y=[20, 14, 23]))
fig.update_layout(template = 'plotly_dark').show()

But nothing happens before CategoryD has a corresponding y value like 15:

Plot 1.3: Added x and y value

Conclusion so far: Adding values to x and y will add another category on the x-axis and a value on the y-axis. As you can see, nothing is getting stacked here quite yet:

enter image description here

Snippet 1.3:

import plotly.graph_objs as go
fig = go.Figure(go.Bar(x=['CategoryA', 'CategoryB', 'CategoryC', 'CategoryD'],
                       y=[20, 14, 23, 15]))
fig.update_layout(template = 'plotly_dark').show()

But what if you add a layout term with barmode='stack'?


Snippet 2:

import plotly.graph_objs as go

fig = go.Figure(go.Bar(x=['CategoryA', 'CategoryB', 'CategoryC', 'CategoryD'],
                       y=[20, 14, 23, 15]))

fig.update_layout(barmode='stack',
                  title = 'Stacked bar chart',
                  template = 'plotly_dark').show()

Plot 2: barmode='stack'

enter image description here

I can understand anyone hoping that this would stack all data within a single trace, but plotly just isn't built that way. To get what you need, you'll have to add another trace using fig.add_trace(go.Bar()) or simply fig.add_bar().

Snippet 3:

import plotly.graph_objs as go
fig = go.Figure(go.Bar(x=['CategoryA', 'CategoryB', 'CategoryC', 'CategoryD'],
                       y=[20, 14, 23, 15]))
fig.add_bar(x=['CategoryA', 'CategoryB', 'CategoryC', 'CategoryD'],
            y=[5, 14, 4, 20])
fig.update_layout(barmode='stack',
                  title = 'Stacked bar chart!',
                  template = 'plotly_dark').show()

Plot 3: Add trace

enter image description here

Notice that neither of the go.Bar() objects have had any name assigned to them, and that plotly by default names them trace 0 and trace 1. So I guess it's more correct to say that a trace contains or 'shows' a plotly graph object rather than calling them the same thing. If you'd like to specify other names, you can do so with, for example, name = 'segment 1' like this:

Snippet 4:

import plotly.graph_objs as go
fig = go.Figure(go.Bar(x=['CategoryA', 'CategoryB', 'CategoryC', 'CategoryD'],
                       y=[20, 14, 23, 15],
                       name = 'segment 1'))
fig.add_bar(x=['CategoryA', 'CategoryB', 'CategoryC', 'CategoryD'],
            y=[5, 14, 4, 20],
            name = 'segment 2')
fig.update_layout(barmode='stack',
                  title = 'Stacked bar chart!',
                  template = 'plotly_dark').show()

Plot 4: Add named traces

enter image description here

If you'd like to 'unstack' your bars, just change barmode to 'group' like this:

fig.update_layout(barmode='group'),

Plot 5:

enter image description here