Hereâs a full example code you can run.
The goal is to make the âmakeStackedâ plot align on the x-axis.
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
# Create plotly figure from params
def make_figure(df2=None, makeStacked=False, debug=True) -> go.Figure:
if debug:
data = {
'Dummy': [0, 0],
'Field': ['Category', 'Category'],
'Group': ['Misc', 'Food'],
'Amount': [-778.69, -589.71],
'Budget': [-500, -500],
'Percent': [155.738, 117.942],
'Margin': [278.69, 89.71],
'Color': ['#D62728', '#D62728'],
}
df_test = pd.DataFrame(data)
print('df_test=\n', df_test)
df2 = df_test.copy()
# figure
fig = go.Figure()
# Whether plot is stacked or grouped
if makeStacked:
x = df2['Dummy']
opacity = 0.5
title = 'Budget (Stacked)'
x_title = ''
barmode_budget = 'relative' # 'group', 'overlay' or 'relative' (default 'relative')
barmode_data = 'relative' # 'group', 'overlay' or 'relative' (default 'relative')
barmode_fig = 'overlay' # 'stack', 'relative', 'group', 'overlay' (default 'relative'?)
# budget
fig1 = px.bar(
data_frame=df2,
x=x,
y=df2['Budget'],
custom_data=['Group', 'Budget', 'Percent', 'Margin'],
opacity=opacity,
barmode=barmode_budget, # 'group', 'overlay' or 'relative' (default 'relative')
).update_traces(
width=0.8,
hovertemplate="<br>".join([
"Group: %{customdata[0]}",
"Budget: $%{customdata[1]:.0f}",
]),
# hovertemplate=None,
# hoverinfo='skip'
)
fig1.data[0]['showlegend'] = True
fig1.data[0]['name'] = 'Budget'
fig1.data[0]['hoverlabel'].namelength = 0
# data
fig2 = px.bar(
data_frame=df2,
x=x,
y=df2['Amount'],
custom_data=['Group', 'Budget', 'Percent', 'Margin'],
# barmode=barmode_data, # 'group', 'overlay' or 'relative' (default 'relative')
).update_traces(
width=0.7,
marker_color=df2['Color'],
hovertemplate="<br>".join([
"Group: %{customdata[0]}",
"Amount: $%{y:.0f}",
"Budget: $%{customdata[1]:.0f}",
"Percent: %{customdata[2]:.1f}%",
"Margin: $%{customdata[3]:.0f}",
]),
)
# fig2.update_layout(barmode=barmode_data)
fig2.data[0]['showlegend'] = True
fig2.data[0]['name'] = 'Data'
fig2.data[0]['hoverlabel'].namelength = 0
# add figs to chart
fig.add_traces([fig1.data[0], fig2.data[0]])
# layout
fig.update_layout(
title=title,
title_x=0.5,
xaxis_title=x_title,
yaxis_title='Amount',
showlegend=True,
# barmode=barmode_fig, # 'stack', 'relative', 'group', 'overlay' (default 'relative'?)
)
return fig
# below is good
else:
x = df2['Group']
opacity = 0.5
title = 'Budget (Grouped)'
x_title = 'Group'
barmode_budget = 'relative' # 'group', 'overlay' or 'relative' (default 'relative')
barmode_data = 'relative' # 'group', 'overlay' or 'relative' (default 'relative')
barmode_fig = 'overlay' # 'stack', 'relative', 'group', 'overlay' (default 'relative'?)
# budget
fig1 = px.bar(
data_frame=df2,
x=x,
y=df2['Budget'],
custom_data=['Group', 'Budget', 'Percent', 'Margin'],
opacity=opacity,
barmode=barmode_budget, # 'group', 'overlay' or 'relative' (default 'relative')
).update_traces(
width=0.8,
hovertemplate="<br>".join([
"Group: %{customdata[0]}",
"Budget: $%{customdata[1]:.0f}",
]),
# hovertemplate=None,
# hoverinfo='skip'
)
fig1.data[0]['showlegend'] = True
fig1.data[0]['name'] = 'Budget'
fig1.data[0]['hoverlabel'].namelength = 0
# data
fig2 = px.bar(
data_frame=df2,
x=x,
y=df2['Amount'],
custom_data=['Group', 'Budget', 'Percent', 'Margin'],
barmode=barmode_data, # 'group', 'overlay' or 'relative' (default 'relative')
).update_traces(
width=0.7,
marker_color=df2['Color'],
hovertemplate="<br>".join([
"Group: %{customdata[0]}",
"Amount: $%{y:.0f}",
"Budget: $%{customdata[1]:.0f}",
"Percent: %{customdata[2]:.1f}%",
"Margin: $%{customdata[3]:.0f}",
]),
)
# fig2.update_layout(barmode=barmode_data)
fig2.data[0]['showlegend'] = True
fig2.data[0]['name'] = 'Data'
fig2.data[0]['hoverlabel'].namelength = 0
# add figs to chart
fig.add_traces([fig1.data[0], fig2.data[0]])
# layout
fig.update_layout(
title=title,
title_x=0.5,
xaxis_title=x_title,
yaxis_title='Amount',
showlegend=True,
barmode=barmode_fig, # 'stack', 'relative', 'group', 'overlay' (default 'relative'?)
)
return fig
# test
# fig = make_figure(makeStacked=False)
# fig.show()
fig = make_figure(makeStacked=True)
fig.show()
I found these settings worked for the âGroupedâ (makeStacked=False) plot in all cases, so I think that part is resolved:
barmode_budget = ârelativeâ
barmode_data = ârelativeâ
barmode_fig = âoverlayâ
However the same settings cause the âBudgetâ trace to overlap on itself, when it should be stacked (relative.) Example below:
Good: both blue and red bars are stacked on each other.
Bad: Red bars should be overlaid on top of blue, not staggered.
Good: Traces are overlaid
Bad: Blue âBudgetâ bars are not stacked correctlyâthey appear to be overlaid on themselves.

