pandas II: Joining, Aggregating, Reshaping, Time Series
Phase 4 goal
Write Python that reads messy program data, transforms it with pandas, and generates finished Excel and Word deliverables (the same kind of document automation your coworker builds), reliably and repeatably.
Environment note: Use your organization's approved Python distribution if one exists. Some environments require specific installers, package mirrors, or a pre-approved package list. Packages used:
pandas,openpyxl,python-docx,matplotlib(and optionallydocxtpl). Work only with the fictional dataset while learning.
π― Learning objectives
Tick each one when you can actually do it.
π‘ Key concepts
- merge:
pd.merge(milestones, programs, on="ProgramID", how="left", validate="many_to_one", indicator=True).indicatorshows unmatched rows (like an anti-join check). - groupby + agg:
summary = (evm.groupby("ProgramID", as_index=False) .agg(BCWP=("BCWP","sum"), ACWP=("ACWP","sum"), BCWS=("BCWS","sum"))) summary["CPI"] = summary.BCWP / summary.ACWP - Cumulative EVM:
evm.sort_values("PeriodEnd").groupby("ProgramID")[["BCWS","BCWP","ACWP"]].cumsum() - pivot_table:
pd.pivot_table(budget, index="ProgramID", columns="FYMonth", values="ActualObligation", aggfunc="sum", fill_value=0) - melt: wide months β long (the Unpivot equivalent).
- Dates:
.dt.year,.dt.month, fiscal year =df.Date.dt.year + (df.Date.dt.month >= 10),pd.offsets.MonthEnd(),.resample("ME")(month-end frequency alias in recent pandas). - Latest snapshot per group:
df.sort_values("PeriodEnd").groupby("ProgramID").tail(1)
π Hands-on exercise: Python EVM Engine
Data: evm_monthly (ProgramID, ContractNumber, WBS, PeriodEnd, BCWS, BCWP, ACWP, BAC, EAC_Contractor), programs.
- Compute cumulative BCWS/BCWP/ACWP per program over time (sum control accounts per program-month first).
- Get the latest period snapshot per program. BAC = sum of control-account BAC in the latest period.
- Calculate CPI, SPI, CV, SV, EAC (BAC/CPI), VAC, TCPI, and EAC Gap vs. EAC_Contractor.
- Merge in ProgramName and Portfolio (with
validate). - Cross-check: your numbers must match the Power BI and Excel results for PRG-005. Write an
assertthat fails if the difference is > $1.
π¦ Mini-project: Budget Execution Analyzer
From budget_execution, produce: (a) FYTD planned vs. actual obligations by program and appropriation, (b) obligation rate and gap to plan, (c) a pivot by FY month, (d) the 5 programs furthest behind plan. Save each as a separate DataFrame, ready for export in 4.4.
π§ Self-check quiz
Answer in your own words, then check. Grade yourself honestly; your score is saved.
validate="many_to_one" protect against?groupby("ProgramID").tail(1) (or idxmax on the date).melt