Reputation: 51
I have a data frame:
import pandas as pd
data = {
'BU': ['A', 'C', 'C', 'E', 'E', 'A', 'D', 'C', 'D', 'E', 'A', 'A', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'A', 'B', 'C', 'E', 'E', 'A', 'A'],
'Sub - BU': ['A2', 'B1', 'C1', 'D1', 'E1', 'A1', 'B1', 'C1', 'D1', 'E2', 'A1', 'B1', 'C1', 'D2', 'E2', 'A1', 'B1', 'C1', 'D1', 'E1', 'C1', 'D2', 'E1', 'E2', 'A1', 'A1'],
'Initial contract result': [0, 2, 0, 1, 3, 2, 0, 0, 0, 9, 0, 5, 2, 0, 0, 8, 7, 4, 0, 0, 0, 0, 5, 0, 8, 4]}
df_cur = pd.DataFrame(data)
df_cur['Contract Sum Type'] = df_cur['Initial contract result'].apply(lambda x: 'Zero' if x == 0 else 'Non-zero')
counts_df = df_cur.groupby(['BU', 'Sub - BU', 'Contract Sum Type']).size().reset_index(name='Count')
group_totals = counts_df.groupby(['BU', 'Sub - BU'])['Count'].transform('sum')
counts_df['Percentage'] = 100 * counts_df['Count'] / group_totals
counts_df['Total Count'] = counts_df.groupby('Sub - BU')['Count'].transform('sum')
Now I want to plot this as a stacked bar chart. On the x axis I want to see the Sub - BU but also I want it to be grouped by the BU column and each BU should get its own colors. Also the stacked bar chart should be descending. How to do this, because the fig.updatelayout commant doesnt seem to do anything in this also I tried creating a subset where I filter the dataframe descending based on the Total Count column but this didnt work.
import plotly.express as px
fig = px.bar(counts_df, x='Sub - BU', y='Count', color='Contract Sum Type',
title='Initial Contract Sum by Sub - BU', barmode='stack', text_auto=True)
fig.update_layout(yaxis={'categoryorder':'total ascending'})
fig.show()
Upvotes: 2
Views: 199
Reputation: 35155
To create a grouping and stacking graph, the x-axis can be graphed by specifying a grouping column and a subgroup column in the list.
import plotly.graph_objects as go
fig = go.Figure()
for t in counts_df['Contract Sum Type'].unique():
dff = counts_df[counts_df['Contract Sum Type'] == t]
fig.add_trace(go.Bar(x=[dff['BU'], dff['Sub - BU']], y=dff['Count'], name=t))
fig.update_layout(barmode='stack', legend_title='Contract Sum Type')
fig.show()
Set different colours for different groups
import plotly.graph_objects as go
import plotly.express as px
colors = px.colors.qualitative.T10
fig = go.Figure()
i = 0
for t in counts_df['Contract Sum Type'].unique():
for g in counts_df['BU'].unique():
dff = counts_df[(counts_df['Contract Sum Type'] == t) & (counts_df['BU'] == g)]
fig.add_trace(go.Bar(x=[dff['BU'], dff['Sub - BU']], y=dff['Count'], name=t, marker=dict(color=colors[i])))
i += 1
# names = set()
# fig.for_each_trace(
# lambda trace:
# trace.update(showlegend=False)
# if (trace.name in names) else names.add(trace.name))
fig.update_layout(barmode='stack', legend_title='Contract Sum Type')
fig.show()
Upvotes: 2
Reputation: 11504
Unless I misunderstand your question you could do something like this:
import pandas as pd
import plotly.express as px
data = {
'BU': ['A', 'C', 'C', 'E', 'E', 'A', 'D', 'C', 'D', 'E', 'A', 'A', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'A', 'B', 'C', 'E', 'E', 'A', 'A'],
'Sub - BU': ['A2', 'B1', 'C1', 'D1', 'E1', 'A1', 'B1', 'C1', 'D1', 'E2', 'A1', 'B1', 'C1', 'D2', 'E2', 'A1', 'B1', 'C1', 'D1', 'E1', 'C1', 'D2', 'E1', 'E2', 'A1', 'A1'],
'Initial contract result': [0, 2, 0, 1, 3, 2, 0, 0, 0, 9, 0, 5, 2, 0, 0, 8, 7, 4, 0, 0, 0, 0, 5, 0, 8, 4]
}
df_cur = pd.DataFrame(data)
df_cur['Contract Sum Type'] = df_cur['Initial contract result'].apply(lambda x: 'Zero' if x == 0 else 'Non-zero')
counts_df = df_cur.groupby(['BU', 'Sub - BU', 'Contract Sum Type']).size().reset_index(name='Count')
group_totals = counts_df.groupby(['BU', 'Sub - BU'])['Count'].transform('sum')
counts_df['Percentage'] = 100 * counts_df['Count'] / group_totals
counts_df['Total Count'] = counts_df.groupby('Sub - BU')['Count'].transform('sum')
# sort by descending Total Count within each BU
counts_df = counts_df.sort_values(['BU', 'Total Count'], ascending=[True, False])
fig = px.bar(counts_df, x='Sub - BU', y='Count', color='Contract Sum Type',
title='Initial Contract Sum by Sub - BU', barmode='stack',
text='Percentage', facet_col='BU', color_discrete_sequence=px.colors.qualitative.Set1)
fig.update_layout(yaxis={'categoryorder': 'total descending'})
fig.show()
which give
Upvotes: 2