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()