HomeCourseModule 15 › User story: build the org chart programmatically

User story: build the org chart programmatically

Module 15 · Scenario: HR & Operations9 min readIntermediate

What you'll learn

  • Walk a parent-pointer hierarchy
  • Count direct and indirect reports
  • Render the org tree as text

The data

emp = pd.read_excel("employees.xlsx")[["employee_id","name","manager_id","title"]]

Build a parent-children map

from collections import defaultdict
children = defaultdict(list)
for _, r in emp.iterrows():
    if pd.notna(r["manager_id"]):
        children[r["manager_id"]].append(r["employee_id"])

names = dict(zip(emp["employee_id"], emp["name"] + " — " + emp["title"]))

def print_tree(emp_id, depth=0):
    print("  " * depth + "• " + names[emp_id])
    for kid in children[emp_id]:
        print_tree(kid, depth + 1)

# Find roots (no manager) and print
roots = emp[emp["manager_id"].isna()]["employee_id"]
for r in roots:
    print_tree(r)

Count direct + indirect reports

def total_reports(emp_id):
    direct = children[emp_id]
    return len(direct) + sum(total_reports(c) for c in direct)

emp["direct_reports"]   = emp["employee_id"].apply(lambda e: len(children[e]))
emp["total_reports"]    = emp["employee_id"].apply(total_reports)
emp.sort_values("total_reports", ascending=False).head(10)

Key takeaways

  • Org chart = flat table with a parent-pointer column.
  • defaultdict(list) makes the children-of-X lookup trivial.
  • Recursion is the natural way to count indirect reports.

Span check

Flag managers with more than 12 direct reports (broad span) or fewer than 3 (too narrow).

📹 Video walkthrough
A video walkthrough of this lesson will be embedded here. Until then, the written walkthrough above mirrors what the video will cover step-for-step.