Hello. I am working on a stacked bar chart, and I would like the order of the bars to be the same as that of the legend. But right now, the bars and the legend are in opposite order as shown in the image attached
This is my code
def plot_employment_by_facility(facilities):
if facilities:
# Since facility is a list (multi-select), use .isin() to filter
filtered_df = df[df[“facility_stationed”].isin(facilities)]
# Group by employment type and count
employment_type_counts = (
filtered_df.groupby("employment_type").size().reset_index(name="counts")
)
# Calculate percentage
employment_type_counts["percentage"] = (
employment_type_counts["counts"] / employment_type_counts["counts"].sum()
) * 100
# Sort alphabetically by employment type
employment_type_counts = employment_type_counts.sort_values(
by="employment_type", ascending=True # Keep ascending order
)
employment_counts = employment_type_counts
# Sort by employment_type to ensure the order is consistent for bars and legend
employment_counts = employment_counts.sort_values("employment_type")
# Create a stacked bar chart with multiple segments for each employment type
employment_counts_fig = go.Figure()
# Define the colors for the employment types
colors = [
"#062d14", # Unpaid Volunteer
"#165e2e", # Permanent Full Time Staff
"#18a145", # Paid Volunteer
"#4cdc7a", # Non-Permanent Contract Staff
]
# Add a segment for each employment type in the stacked bar in the same order as legend
for i, row in employment_counts.iterrows():
employment_counts_fig.add_trace(
go.Bar(
x=[row["percentage"]], # Percentage for this employment type
name=row["employment_type"], # Employment type as the label
orientation="h",
hovertemplate=f"Employment Type: {row['employment_type']}<br>Count: {row['counts']}<br>Percentage: {row['percentage']:.2f}%<extra></extra>",
text=f"{row['employment_type']}: {row['percentage']:.2f}%",
textposition="none", # Hide the text inside the bar
marker_color=colors[
i % len(colors)
], # Cycle through the defined colors
)
)
# Update the layout for the figure
employment_counts_fig.update_layout(
title={
"text": "<b><u>% Health Workers by Employment Type</u></b>",
"font": {"color": "#1E1E1E"},
},
xaxis_title="",
barmode="stack", # Stack the bars horizontally
showlegend=True, # Show the legend for the employment types
legend_title_text="Workers Group", # Custom legend title
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
yaxis_title="", # Remove the y-axis title
height=200, # Adjust the height of the chart here
legend=dict(
orientation="h", # Horizontal legend
yanchor="top", # Aligns the top of the legend box with the position defined by 'y'
y=-0.6, # Move the legend further down to add more space
xanchor="center", # Center the legend horizontally
x=0.5, # Position it at the center of the chart
),
)
# Optional: Customize y-axis ticks if needed
employment_counts_fig.update_yaxes(
tickmode="auto", # Ensure tickmarks display correctly
showline=True, # Show the axis line
zeroline=False, # Disable the "zero" reference line
showgrid=True, # Optionally, show or hide the gridlines
)
employment_counts_fig.show()
Example usage: Plot for specific facilities
selected_facilities = [“Facility 1”, “Facility 2”]
plot_employment_by_facility(selected_facilities)
I would appreciate any help to get the order of the legend to be the same as the labels on the bars. Thank you