Python for Analytics
Intermediate 13 min read Python for Analytics

Clean, Maintainable Analysis Code

Code that survives its author

Analyses that can't be re-run, debugged or handed off are debt. Naming, typing, function boundaries, docstrings and reproducibility turn throwaway scripts into assets.

readabilitytype hintsdocstringsreproducibilityrefactoringmodules
Prerequisites: Working with Files
Before we start

What you will learn

  • Name functions, variables and files to read as prose
  • Use type hints and docstrings as executable documentation
  • Structure analyses into importable, re-runnable modules
Introduction

What is this?

Clean analysis code is reproducibility plus legibility: functions named as verbs, variables named as nouns, types declared, steps isolated, and every run leaving the inputs untouched. It means someone else — or you, in six weeks — can pick up the script, understand intent, and re-run it to identical results.

Motivation

Why do you need it?

  • Analyses are re-run constantly; a script that needs rewiring each time is a tax on every rerun.
  • Clear names reduce the 'what was this column again?' tax tenfold.
  • Type hints catch whole bug classes before the program runs.
  • Trust: stakeholders rely on figures that can be re-derived from source by anyone.
Think about it

Mental model

Imagine

A well-labeled, documented kitchen vs a chef's hidden notebooks

Think of

Clean analysis code

The covered recipe kitchen lets any cook reproduce the dish exactly. A chaotic pantry with unnamed sauces might produce tonight's plate but nothing anyone can repeat — same is true of analysis scripts.

Mechanics

How it works

  • Refactor repeated SQL/Pandas blocks into one named function with a signature that states intent.
  • Name variables as data (raw_revenue, active_users) not mechanics (x1, tmp2).
  • Add type hints (prices: pd.Series -> float) that double as documentation.
  • Write 1-3 line docstrings stating the what and the why, not the how.
  • Isolate config (paths, thresholds) at the top so runs are parameterized, not edited.
  • Keep raw inputs untouched, writes to a distinct output dir, and pin versions.

From throwaway to asset.

Raw script
Split
Name + type
Configure
Re-runnable
Hands-on

Examples

Dirty vs clean shape

Dirty vs clean shape
# tens of lines of df manipulation... then:
def compute_mrr(df: pd.DataFrame, price_col: str = "price") -> float:
"""Total monthly-recurring revenue for active subscriptions."""
active = df[df["status"] == "active"]
return (active[price_col] * active["quantity"]).sum()
# config isolated:
INPUT = Path("exports/mrr_2026-06.csv")
OUTPUT = Path("reports/mrr_summary.csv")
THRESHOLDS = {"active_min_days": 30}

One named, typed, documented function plus top-of-file config makes the whole analysis inspectable and re-runnable.

Real world

In production

  • A weekly pipeline lives as importable modules (ingest.py, clean.py, report.py) with a thin run.py entry.
  • A hand-off analysis uses type-annotated functions so the downstream team reuses logic instead of re-deriving it.
  • An audit trail: config files and pinned versions let compliance re-run any quarter's numbers.
Guidelines

Best practices

  • Functions return values instead of printing — output is decided by the caller.
  • Split scripts into steps visible on one screen; a wall of 200 lines hides the story.
  • Add an if __name__ == '__main__': guard so modules import without side effects.
  • Commit the code and the data contract file, never the secrets.
Watch out

Common mistakes

  • Magic numbers buried mid-file ('if x > 30') with no explanation of the 30.
  • Functions that mutate their inputs, making idempotence impossible.
  • Docstrings that restate the code instead of the 'why'.
  • Paths, thresholds and seeds duplicated across files so reruns drift.
When things break

Debugging tips

  • If the 'same script' gives different results across runs, hunt for unseeded sampling or nondeterministic ordering.
  • When a coworker misreads a name, rename it — names are documentation with a beating heart.
  • Divide a failing step into a tiny reproduce.py that isolates one function on five rows.
  • Run with -W error to surface warnings you were ignoring.
Interviews

Interview checkpoint

Test yourself

Quick quiz

0/2
1

The best reason to prefer functions over one long script:

2

Type hints only help editors, never catch real bugs.

Go deeper

Official documentation