Waterfall Chart
Headcount Changes Analysis
Workforce planning waterfall showing hiring, attrition, and restructuring impacts.
Output
Python
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Patch
# Headcount changes
categories = ['Start\nof Year', 'New\nHires', 'Internal\nTransfers', 'Promotions',
'Voluntary\nAttrition', 'Involuntary\nSeparations', 'Contractor\nConversions', 'End\nof Year']
values = [0, 145, 0, 0, -68, -35, 22, 0]
# Calculate running total
initial = 520
running_total = initial
bottoms = []
heights = []
colors = []
for i, (cat, val) in enumerate(zip(categories, values)):
if cat == 'Start\nof Year':
bottoms.append(0)
heights.append(initial)
colors.append('#27D3F5')
elif cat == 'End\nof Year':
bottoms.append(0)
heights.append(running_total)
colors.append('#6CF527')
elif 'Transfer' in cat or 'Promotion' in cat:
bottoms.append(running_total - 10)
heights.append(20)
colors.append('#F5B027')
elif val > 0:
bottoms.append(running_total)
heights.append(val)
colors.append('#27F5B0')
running_total += val
else:
bottoms.append(running_total + val)
heights.append(abs(val))
colors.append('#F5276C')
running_total += val
# Create figure with light theme
fig, ax = plt.subplots(figsize=(14, 8), facecolor='#ffffff')
ax.set_facecolor('#ffffff')
x = np.arange(len(categories))
bars = ax.bar(x, heights, bottom=bottoms, color=colors, width=0.65, edgecolor='#e5e7eb', linewidth=1)
# Add value labels
for i, (bar, val, bot, height) in enumerate(zip(bars, values, bottoms, heights)):
y_pos = bot + height / 2
if categories[i] in ['Start\nof Year', 'End\nof Year']:
label = f"{height}"
ax.text(bar.get_x() + bar.get_width()/2, y_pos, label,
ha='center', va='center', fontsize=12, fontweight='bold', color='white')
elif 'Transfer' in categories[i] or 'Promotion' in categories[i]:
label = "0"
ax.text(bar.get_x() + bar.get_width()/2, y_pos, label,
ha='center', va='center', fontsize=10, fontweight='bold', color='#0a0a0f')
else:
label = f"+{val}" if val > 0 else f"{val}"
ax.text(bar.get_x() + bar.get_width()/2, y_pos, label,
ha='center', va='center', fontsize=10, fontweight='bold', color='white')
# Styling
ax.set_xlim(-0.6, len(categories) - 0.4)
ax.set_ylim(0, max(bottoms[i] + heights[i] for i in range(len(heights))) * 1.1)
ax.set_xticks(x)
ax.set_xticklabels(categories, fontsize=9, color='#374151')
ax.set_ylabel('Headcount', fontsize=12, color='#374151', fontweight='500')
ax.set_title('Annual Workforce Planning Analysis', fontsize=16, color='#111827', fontweight='bold', pad=20)
ax.tick_params(axis='y', colors='#374151', labelsize=10)
ax.yaxis.grid(True, linestyle='--', alpha=0.4, color='#e5e7eb')
ax.set_axisbelow(True)
for spine in ax.spines.values():
spine.set_color('#d1d5db')
# Legend outside plot
legend_elements = [
Patch(facecolor='#27D3F5', label='Starting Headcount'),
Patch(facecolor='#27F5B0', label='Additions'),
Patch(facecolor='#F5B027', label='Neutral Movements'),
Patch(facecolor='#F5276C', label='Separations'),
Patch(facecolor='#6CF527', label='Ending Headcount')
]
ax.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(0, -0.1),
ncol=5, fontsize=8, facecolor='white', edgecolor='#d1d5db', labelcolor='#374151')
plt.tight_layout()
plt.subplots_adjust(bottom=0.15)
plt.show()
Library
Matplotlib
Category
Financial
More Waterfall Chart examples
☕