Logan's Analytics Bootcamp
Dashboard β€Ί Phase 4: Python for Report Automation
M4.2

pandas I: Loading, Cleaning, Selecting

⏱ 8 hoursπŸ“… Weeks 20–21❓ 4 quiz questions
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 optionally docxtpl). Work only with the fictional dataset while learning.

🎯 Learning objectives

Tick each one when you can actually do it.

πŸ’‘ Key concepts

  • Loading: pd.read_csv(), pd.read_excel(path, sheet_name=None, skiprows=3) (dict of all sheets), usecols, dtype.
  • Inspecting: .head(), .info(), .describe(), .shape, .isna().sum(), .value_counts().
  • Selecting: df["col"], df[["a","b"]], df.loc[row_filter, cols], boolean masks: df[(df.Status=="Open") & (df.Score>=15)], .query("SlipDays > 30").
  • New columns: vectorized math df["CPI"] = df.BCWP / df.ACWP, np.where, .map(dict), .apply (sparingly).
  • Cleaning:
    • pd.to_datetime(df.ForecastDate, errors="coerce") (TBD β†’ NaT)
    • df.col.str.strip().str.upper()
    • money parsing via .str.replace + a function for M/K suffixes
    • .fillna(), .dropna(subset=[...]), .drop_duplicates()
    • .rename(columns={...}) with a header-variant map
  • pandas 3.x notes: Copy-on-Write is now the default (avoids "SettingWithCopy" confusion), and a dedicated string dtype is the default for text columns. Assign results back explicitly: df = df.assign(...).

πŸ›  Hands-on exercise: Clean the Status Drops in pandas

⬇ Practice data for this module
D1 programsProgram dimension (12 rows)CSVXLSX
D2 milestonesMilestones (~150 rows)CSVXLSX
D3 evm_monthlyMonthly EVM by control account (~2,000 rows)CSVXLSX
D4 contractsContracts (30 rows)CSVXLSX
D5 budget_executionBudget execution by appropriation (1,296 rows)CSVXLSX
D6 schedule_tasksIMS task export (1,500 rows)CSVXLSX
D7 risksRisk register (80 rows)CSVXLSX
D8 status_drops/36 messy monthly status workbooksZIPBrowse files

Data: status_drops/ (D8 messy files).

  1. Use Path.glob("PRG-*_Status_*.xlsx") to loop over files, read_excel(skiprows=…) each one, and add SourceFile.
  2. Normalize headers with a mapping dict ({"Fcst Dt": "ForecastDate", "Est. Completion": "ForecastDate", ...}).
  3. Concatenate with pd.concat.
  4. Clean RAG (.str.strip().str.upper().map({"G":"Green","GREEN":"Green","GRN":"Green",...})).
  5. Parse dates (coerce) and money (custom function). Add DateQualityFlag.
  6. Save to status_clean.csv and compare row counts with your Power Query output from Module 1.4. They should match.

πŸ“¦ Mini-project: Data Quality Report

A script that loads all D1–D7 datasets and prints/saves a data quality summary: row counts, % missing per column, duplicate keys, orphaned foreign keys (e.g., milestones whose ProgramID isn't in programs), dates outside the program baseline window, and negative dollar values. Output: dq_report.csv.

🧠 Self-check quiz

Answer in your own words, then check. Grade yourself honestly; your score is saved.

Q4.2.1
What does errors="coerce" do in pd.to_datetime?
Write at least a few words to unlock.
Q4.2.2
Write a filter for open risks with score β‰₯ 15, where score = Likelihood Γ— Consequence.
Write at least a few words to unlock.
Q4.2.3
Why prefer vectorized operations over .apply or loops?
Write at least a few words to unlock.
Q4.2.4
How do you read every sheet of a workbook at once?
Write at least a few words to unlock.