Personal Budget Analyzer
Turn a month of raw expenses into a full spending report with category totals, percentages and a text bar chart — the same analysis every budgeting app performs.
How it works in the real world
Every budgeting app (YNAB, Revolut analytics, your bank's spending view) runs this exact pipeline:
- Ingest — raw transactions arrive as (category, amount) records.
- Aggregate — sum per category with a dictionary.
- Analyse — turn totals into percentages and find the biggest drain.
- Present — format a report humans actually read.
You'll build each stage as its own step — by the end you have a working analyzer you could point at your own bank export.
Total up the month
Loop over expenses and print the total as Total spent: 1295.
Unpack in the loop: for category, amount in expenses: — add each amount to a running total.
expenses = [("rent", 800), ("food", 240), ("transport", 90), ("fun", 120), ("subscriptions", 45)]
total = 0
for category, amount in expenses:
total += amount
print(f"Total spent: {total}")
Run your code to check this step…
Group by category
Real data has repeat categories. Build a dict of per-category totals and print each as category: total (in first-seen order).
totals[category] = totals.get(category, 0) + amount — then loop totals.items().
expenses = [("food", 120), ("rent", 800), ("food", 95), ("transport", 60), ("fun", 150), ("transport", 40)]
totals = {}
for category, amount in expenses:
totals[category] = totals.get(category, 0) + amount
for category, amount in totals.items():
print(f"{category}: {amount}")
Run your code to check this step…
Percentages & the biggest drain
Print each category as category: XX.X% of total spending (1 decimal), then Biggest: rent for the largest category.
f"{amount / grand * 100:.1f}%" formats the share; max(totals, key=totals.get) finds the biggest key.
totals = {"food": 215, "rent": 800, "transport": 100, "fun": 150}
grand = sum(totals.values())
for category, amount in totals.items():
print(f"{category}: {amount / grand * 100:.1f}%")
print(f"Biggest: {max(totals, key=totals.get)}")
Run your code to check this step…
The final report
Ship it: print a header === July Budget ===, one aligned line per category ({category:<12}{amount} plus a bar of # per full 100), and Total: 1265.
f"{category:<12}{amount} " + "#" * (amount // 100) — the :<12 pads the name to 12 characters.
totals = {"food": 215, "rent": 800, "transport": 100, "fun": 150}
print("=== July Budget ===")
for category, amount in totals.items():
print(f"{category:<12}{amount} " + "#" * (amount // 100))
print(f"Total: {sum(totals.values())}")
Run your code to check this step…
Project shipped!
You just built a complete, working personal budget analyzer — the same architecture running in production software. Pick your next build →