Stacked bar chart with two y axis

Hi,
I have a dataframe with values,
the values are normalized to percentages, (sum up to 100%)
I want to have a stacked bar chart for those values, where on the first y axis I will have the percentages show up, and on the second y axis (lets say on the right), I will have the numerical value of those values show up.
an example dataframe can be the following:
data = {
‘Category’: [‘A’, ‘B’, ‘C’, ‘D’],
‘Value1’: [10, 20, 30, 40],
‘Value2’: [15, 25, 35, 25],
‘Value3’: [25, 10, 20, 45],
‘NormalizationFactor’: [50, 55, 85, 110]
}

df = pd.DataFrame(data)
df[[‘Value1_%’, ‘Value2_%’, ‘Value3_%’]] = df[[‘Value1’, ‘Value2’, ‘Value3’]].div(df[‘NormalizationFactor’], axis=0) * 100
would apricate some help on the subject, didn’t manage to solve this.

thanks !

import pandas as pd
import matplotlib.pyplot as plt

# Sample data
data = {
    'Category': ['A', 'B', 'C', 'D'],
    'Value1': [10, 20, 30, 40],
    'Value2': [15, 25, 35, 25],
    'Value3': [25, 10, 20, 45],
    'NormalizationFactor': [50, 55, 85, 110]
}

# Create DataFrame
df = pd.DataFrame(data)

# Normalize the values to percentages
df[['Value1_%', 'Value2_%', 'Value3_%']] = df[['Value1', 'Value2', 'Value3']].div(df['NormalizationFactor'], axis=0) * 100

# Plotting
fig, ax1 = plt.subplots(figsize=(10, 6))

# Stacked bar chart for percentages
categories = df['Category']
values_percentage = df[['Value1_%', 'Value2_%', 'Value3_%']].T

values_percentage.columns = categories
values_percentage.plot(kind='bar', stacked=True, ax=ax1, colormap='viridis', edgecolor='black')

# Set labels for the primary y-axis (percentages)
ax1.set_ylabel('Percentage')
ax1.set_xlabel('Category')
ax1.set_xticks(range(len(categories)))
ax1.set_xticklabels(categories)
ax1.legend(title='Values', bbox_to_anchor=(1.05, 1), loc='upper left')

# Create a secondary y-axis
ax2 = ax1.twinx()

# Set limits for the secondary y-axis based on actual values
max_value = df[['Value1', 'Value2', 'Value3']].values.max()
ax2.set_ylim(0, max_value * 3)

# Add the actual values as text annotations on the bars
for i, (value1, value2, value3) in enumerate(zip(df['Value1'], df['Value2'], df['Value3'])):
    ax2.text(i, df['Value1_%'][i] / 2, f'{value1}', ha='center', va='center', color='white', weight='bold')
    ax2.text(i, df['Value1_%'][i] + df['Value2_%'][i] / 2, f'{value2}', ha='center', va='center', color='white', weight='bold')
    ax2.text(i, df['Value1_%'][i] + df['Value2_%'][i] + df['Value3_%'][i] / 2, f'{value3}', ha='center', va='center', color='white', weight='bold')

# Set labels for the secondary y-axis (actual values)
ax2.set_ylabel('Actual Values')

plt.title('Stacked Bar Chart with Percentages and Actual Values')
plt.show()