Waterfall Chart

Capital Expenditure Analysis

CapEx waterfall showing investment allocation across facilities, equipment, and technology.

Output
Capital Expenditure Analysis
Python
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Patch

# CapEx allocation (in millions)
categories = ['Total\nBudget', 'Facility\nExpansion', 'Manufacturing\nEquipment', 'IT\nInfrastructure', 
              'R&D\nLabs', 'Fleet\nVehicles', 'Safety\nUpgrades', 'Remaining\nBudget']
values = [0, -45, -82, -35, -28, -15, -12, 0]

# Calculate running total
initial = 250
running_total = initial
bottoms = []
heights = []
colors = []

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

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

# Create figure
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)

# Add value labels
for i, (bar, val, bot, height) in enumerate(zip(bars, values, bottoms, heights)):
    y_pos = bot + height / 2
    if categories[i] == 'Total\nBudget':
        label = f"${height}M"
        ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, 
                ha='center', va='center', fontsize=11, fontweight='bold', color='white')
    elif categories[i] == 'Remaining\nBudget':
        label = f"${height}M"
        ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, 
                ha='center', va='center', fontsize=11, fontweight='bold', color='#0a0a0f')
    else:
        label = f"${abs(val)}M"
        ax.text(bar.get_x() + bar.get_width()/2, y_pos, label, 
                ha='center', va='center', fontsize=10, fontweight='bold', color='white')

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

# Styling
ax.set_xlim(-0.6, len(categories) - 0.4)
ax.set_ylim(0, initial * 1.1)
ax.set_xticks(x)
ax.set_xticklabels(categories, fontsize=9, color='#e2e8f0')
ax.set_ylabel('Budget ($ Millions)', fontsize=12, color='#e2e8f0', fontweight='500')
ax.set_title('Annual CapEx Allocation Breakdown', 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')

# Percentage utilization annotation
utilized = initial - running_total
pct = (utilized / initial) * 100
ax.annotate(f'Budget Utilization: {pct:.1f}%', xy=(0.98, 0.95), xycoords='axes fraction',
            fontsize=11, color='#27F5B0', ha='right', fontweight='bold',
            bbox=dict(boxstyle='round,pad=0.4', facecolor='#1e293b', edgecolor='#27F5B0', alpha=0.9))

# Legend outside plot - simplified
legend_elements = [
    Patch(facecolor='#4927F5', label='Total Budget'),
    Patch(facecolor='#F5276C', label='Expenditures'),
    Patch(facecolor='#27D3F5', label='Remaining')
]
ax.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(0, -0.1), 
          ncol=3, 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