79808410

Date: 2025-11-04 00:07:33
Score: 1.5
Natty:
Report link

Plot

[image](https://i.stack.imgur.com/abcd1.png)

Import Packages

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns  # just included to set plot style
sns.set_theme(style="darkgrid")

Generate Fake Data

days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
df = pd.DataFrame(
    dict(
        year=[2023]*7 + [2024]*7 + [2025]*7,
        day_of_week=days_of_week * 3,
        avg_cardio_minutes=[20, 15, 10, 25, 30, 5, 0,
                                    25, 20, 15, 30, 35, 10, 5,
                                    30, 25, 20, 35, 40, 15, 10],
        avg_lifting_minutes=[40, 35, 30, 45, 50, 25, 20,
                                     45, 40, 35, 50, 55, 30, 25,
                                     50, 45, 40, 55, 60, 35, 30]
    )
)

enter image description here

def plot_stacked_grouped_bar_chart(df, x_major_column, x_minor_column, stack_columns,
                                     stack_labels=None, y_label='', title='', legend_title=''):
    """
    Plots a stacked grouped bar chart with the specified data and labels.
    
    Parameters:
    -----------
    df : pd.DataFrame
        DataFrame containing the data to plot.
    x_major_column : str
        Column name for the major x-axis grouping.
    x_minor_column : str
        Column name for the minor x-axis grouping.
    stack_columns : list of str
        List of column names to stack.
    stack_labels : list of str, optional
        List of labels for the stacked columns. If None, uses stack_columns.
    y_label : str, optional
        Label for the y-axis.
    title : str, optional
        Title of the plot.
    legend_title : str, optional
        Title of the legend.
    """

    if stack_labels is None:
        stack_labels = stack_columns

    fig, ax = plt.subplots(figsize=(10, 5))

    x_major_values = df[x_major_column].unique().tolist()
    offset = 0
    xtick_labels = []
    # iterate over major x-axis groups
    for i, major_value in enumerate(x_major_values):
        df_major = df[df[x_major_column] == major_value]
        x_minor_values = df_major[x_minor_column].unique().tolist()
        x_positions = offset + np.arange(len(x_minor_values))  # the label locations
        bottoms = np.zeros(len(x_minor_values))
        # iterate over stack columns
        for j, stack_column in enumerate(stack_columns):
            heights = df_major[stack_column].values    
            ax.bar(x=x_positions, height=heights, color=f'C{j}', width=1, label=stack_labels[j], bottom=bottoms)
            bottoms += heights
        # add major x-axis label
        ax.text(offset + len(x_minor_values) / 2 - 0.5, -0.2, major_value, ha='center', va='top', transform=ax.get_xaxis_transform())
        # update offset and xtick labels
        offset += len(x_minor_values)
        xtick_labels.extend([x_minor_values])
        if i < len(x_major_values) - 1:
            offset += 1  # space between major groups
            xtick_labels.append('')  # empty label for space
    ax.set_xticks(range(offset))
    ax.set_xticklabels(days_of_week + [""] + days_of_week + [""] + days_of_week, rotation=45)

    ax.set_ylabel(y_label)
    ax.set_title(title)
    
    # reorder legend to match stack order
    handles, labels = ax.get_legend_handles_labels()
    handles = handles[::-1][:len(stack_labels)]
    labels = labels[::-1][:len(stack_labels)]
    ax.legend(title=legend_title, handles=handles, labels=labels)
    
    plt.show()

plot_stacked_grouped_bar_chart(df=df,
                               x_major_column = 'year',
                               x_minor_column = 'day_of_week',
                               stack_columns = ['avg_lifting_minutes', 'avg_cardio_minutes'],
                               stack_labels = ['Lifting', 'Cardio'],
                               y_label = 'minutes',
                               title = 'Average Time Working out per Day of Week',
                               legend_title = 'Workout Type')
Reasons:
  • Blacklisted phrase (1): enter image description here
  • Probably link only (1):
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: sthobbs