Waterfall Chart

Employee Compensation Breakdown

Total compensation waterfall from base salary through benefits and taxes.

Output
Employee Compensation Breakdown
Python
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Patch

categories = ['Base\nSalary', 'Annual\nBonus', 'Stock\nGrants', 'Health\nInsurance', 
              '401k\nMatch', 'Payroll\nTaxes', 'Other\nBenefits', 'Total\nComp Cost']
values = [0, 25, 40, 18, 8, 15, 6, 0]

initial = 120
running_total = initial
bottoms, heights, colors = [], [], []

palette = ['#6CF527', '#4927F5', '#27D3F5', '#F5B027', '#F5276C', '#27F5B0']

for i, (cat, val) in enumerate(zip(categories, values)):
    if 'Base' in cat:
        bottoms.append(0)
        heights.append(initial)
        colors.append('#27D3F5')
    elif 'Total' in cat:
        bottoms.append(0)
        heights.append(running_total)
        colors.append('#F5276C')
    else:
        bottoms.append(running_total)
        heights.append(val)
        colors.append(palette[(i-1) % len(palette)])
        running_total += val

fig, ax = plt.subplots(figsize=(14, 8), facecolor='#0a0a0f')
ax.set_facecolor('#0a0a0f')

x = np.arange(len(categories))
bars = ax.bar(x, heights, bottom=bottoms, color=colors, width=0.65, edgecolor='#1e293b', linewidth=1)

for i, (bar, val, bot, height) in enumerate(zip(bars, values, bottoms, heights)):
    y_pos = bot + height / 2
    if 'Base' in categories[i] or 'Total' in categories[i]:
        label = f"${height}K"
        ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, ha='center', va='center', 
                fontsize=11, fontweight='bold', color='white')
    else:
        label = f"+${val}K"
        ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, ha='center', va='center', 
                fontsize=10, fontweight='bold', color='white')

for i in range(len(x) - 1):
    y = bottoms[i] + heights[i]
    ax.plot([x[i] + 0.35, x[i+1] - 0.35], [y, y], color='#475569', linestyle='--', linewidth=1.5, alpha=0.7)

ax.set_xlim(-0.6, len(categories) - 0.4)
ax.set_ylim(0, running_total * 1.1)
ax.set_xticks(x)
ax.set_xticklabels(categories, fontsize=9, color='#e2e8f0')
ax.set_ylabel('Annual Amount ($ Thousands)', fontsize=12, color='#e2e8f0', fontweight='500')
ax.set_title('Total Employee Compensation Cost', fontsize=16, color='white', fontweight='bold', pad=20)
ax.tick_params(axis='y', colors='#e2e8f0', labelsize=10)
ax.yaxis.grid(True, linestyle='--', alpha=0.3, color='#334155')
ax.set_axisbelow(True)
for spine in ax.spines.values():
    spine.set_color('#334155')

burden_rate = ((running_total - initial) / initial) * 100
ax.annotate(f'Benefits Burden Rate: {burden_rate:.0f}%', xy=(0.98, 0.95), xycoords='axes fraction',
            fontsize=11, color='#F5B027', ha='right', fontweight='bold',
            bbox=dict(boxstyle='round,pad=0.4', facecolor='#1e293b', edgecolor='#F5B027', alpha=0.9))

legend_elements = [Patch(facecolor='#27D3F5', label='Base Salary'), Patch(facecolor='#6CF527', label='Cash Comp'),
                   Patch(facecolor='#F5B027', label='Benefits'), Patch(facecolor='#F5276C', label='Total Cost')]
ax.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(0, -0.1), ncol=4, fontsize=9,
          facecolor='#1e293b', edgecolor='#334155', labelcolor='white')

plt.tight_layout()
plt.subplots_adjust(bottom=0.15)
plt.show()
Library

Matplotlib

Category

Financial

Did this help you?

Support PyLucid to keep it free & growing

Support