Seven lessons, about an hour and 15 minutes. You'll take module 2's manual Excel report and turn it into a script that runs itself.
Python is not a strictly better version of Excel — it's a different tool, right for different jobs. Reaching for it out of habit, on a task Excel handles fine, wastes time relearning syntax for no real benefit.
| Python wins when | The same cleaning steps need to run on a new file every week (module 2's Power Query problem, but for cases Power Query can't reach); the data is too large to comfortably open in Excel; the logic is genuinely complex — multi-step joins, custom rules — and needs to live somewhere reviewable and testable. |
| Excel wins when | Chidi or a branch manager needs to open the result themselves and poke at it; the task is a one-off; the audience for the output isn't technical. |
The question isn't "which tool is more powerful." It's "which tool gets this specific job done and handed off cleanly." Often that's still Excel.
A pandas DataFrame is the Python equivalent of an Excel Table from module 2 — rows and named columns, and every operation you already know from SQL and Excel has a close pandas equivalent. Open the starter kit's clean_and_report.py alongside this lesson.
| Load | df = pd.read_csv('raw_sales.csv', parse_dates=['date']) — parse_dates matters, the same way lesson 4.3's type-checking mattered in Excel. |
| Filter | df[df['transaction_type'] == 'SALE'] — the pandas equivalent of a WHERE clause. |
| Group | df.groupby('branch')['revenue'].sum() — the pandas equivalent of SQL's GROUP BY, or Excel's pivot table. |
| Inspect the shape | df.shape, df.head(), df.dtypes — module 4's profiling habit, in three lines. |
Notice how much of this module is really module 1 through 6's habits, expressed in a different syntax — know the grain, filter honestly, check types, aggregate deliberately. The tool changes far more than the thinking does.
Lesson 3.3's fan-out join trap applies exactly as much in pandas as in SQL. pd.merge(sales, products, on='sku') can silently multiply rows if products has duplicate SKUs — the fix is the same habit: check len(sales) before and after the merge.
before = len(sales)
merged = pd.merge(sales, products, on='sku', how='left')
assert len(merged) == before, "merge changed row count — check for duplicate SKUs"
The assert isn't decoration — it stops the script outright, loudly, the moment a fan-out happens, rather than letting a quietly-inflated total flow into the rest of the report.
how='left' matters too: it keeps every row from sales even when a SKU has no match in products, rather than silently dropping transactions the way an inner join would — the pandas equivalent of choosing carefully between an INNER and LEFT JOIN in SQL.
The starter kit's load_and_clean() function is deliberately separated from weekly_summary() — this is the single habit that makes a script reusable rather than a one-off notebook of commands run in whatever order you happened to type them.
A function with a clear name, a defined input, and a defined output can be rerun on next week's file by changing exactly one line — the file path — rather than re-deriving the whole sequence of steps from memory. This is Power Query's "record once, replay on refresh" idea, written as code instead of clicked as steps.
Could someone else — or you, in three months — run this on a brand-new file without reading every line first? If yes, you've built something reusable. If the answer is "they'd need to understand my whole thought process first," it's still a scratch notebook wearing a .py extension.
A one-line df.groupby('date')['revenue'].sum().plot() is for you, right now, spotting a pattern while you're still exploring — not for Chidi. Module 9's lesson on charts that argue is about deliberate, polished presentation; this is the opposite instinct, deliberately rough and fast.
Don't spend ten minutes styling a chart you're going to look at once and delete. If a quick matplotlib plot reveals something worth showing Chidi, that finding gets rebuilt properly — in Power BI, or as a deliberately designed chart — using module 9's discipline, not shipped as-is from an exploratory script.
Module 2's manual Monday-morning cleanup — nine branch CSVs, cleaned by hand every week — is exactly the kind of recurring task lesson 7.4's reusable function is built for. Once load_and_clean() and weekly_summary() exist as functions, wiring them into a fully automated report is mostly plumbing: a scheduled task that runs the script and emails or saves the output, with no manual step in between.
You don't need to be a software engineer to benefit from git — you need three habits, consistently, and they cover most of what actually goes wrong with analyst code in practice.
Have Python and pandas installed (pip install pandas) — this drill runs real code against the starter kit's CSV.
Starting from the starter kit's clean_and_report.py, extend it to fully replace module 2's manual Monday-morning process.
Whether you can extend real working code without breaking it — adding a join safely, handling a missing file gracefully, and leaving it in a state someone else could actually run. That is the entire point of module 7: not learning Python syntax in the abstract, but replacing a real manual process with something that runs itself.
Module 8 turns to working with AI tools directly — reviewing AI-drafted SQL and formulas, including ones an AI might suggest for a script exactly like the one you just built.