Module 1 · Foundations and Reproducibility

Define the Question, Row Grain, and Metric Contract

Lesson 1 of 32 5 min read Updated

Module 1: Foundations and Reproducibility · Lecture 1 of 32

A correct calculation can still answer the wrong question. Begin the course by turning “how is the store doing?” into a precise decision, a table grain, and a revenue definition that another analyst can reproduce.

What you will learn

  • Distinguish an observation from a business entity.
  • Define revenue and its denominator before writing a formula.
  • Reconcile gross value, discounts, refunds, and cancellations.

Understand the problem

Start with a decision

Imagine a fictional retailer reviewing its January–March 2026 trading. The manager wants to understand which channels contribute net merchandise revenue and whether changes deserve further investigation. “Increase sales” is too broad: it does not specify a time window, population, unit, or action. A useful first question is: among accepted, non-cancelled orders in this export, how much merchandise revenue remains after discounts and recorded refunds?

Declare the grain

The clean orders table has one row per order. The raw export can repeat an order, and the customer dimension has one row per customer. An order is not a line item, payment, shipment, or customer. Counting rows before removing exact duplicates inflates orders; counting customers after a one-to-many join can inflate customers. Write the grain above every table in your analysis notebook.

Write the contract

All money is integer paise. Gross merchandise value equals units multiplied by unit price. Net merchandise revenue equals gross minus discount minus refunded amount, with cancelled orders contributing zero. This is a teaching definition for this export, not an accounting standard. It excludes tax, shipping charges, cost of goods, marketing spend, unrecorded refunds, and settlement timing. Average order value uses non-cancelled orders, including fully returned orders; its denominator is not just orders with positive revenue.

Separate observation from explanation

A channel total describes the rows assigned to that channel. It does not prove marketing caused the sales. The dataset is deliberately synthetic, with deterministic patterns and planted defects. Use it to practise methods, never to make claims about real customers, market behavior, or advertising returns.

Run the worked example

Download and extract the course kit linked below. Open a terminal in the extracted folder, complete the setup in Lecture 2, and run python run_course.py --lesson 1 --examples-only. Each script starts from the shared dataset; it does not depend on a notebook cell from another lecture. All retail records are fictional and amounts are integer paise unless a chart explicitly says INR.

from pathlib import Path
import numpy as np
import pandas as pd
from course_data import load_orders, load_raw, load_customers, clean_orders, ROOT, OUT

orders = load_orders()
eligible = orders.loc[orders['status'].ne('cancelled')]
net = int(orders['net_paise'].sum())
denominator = len(eligible)
print('Accepted orders:', len(orders))
print('Non-cancelled orders:', denominator)
print('Net merchandise revenue (INR):', round(net / 100, 2))
print('Net AOV (INR):', round(net / denominator / 100, 2))
assert orders['order_id'].is_unique
assert orders.loc[orders['status'].eq('cancelled'), 'net_paise'].eq(0).all()
assert orders['net_paise'].ge(0).all()

Verified output

Accepted orders: 239
Non-cancelled orders: 224
Net merchandise revenue (INR): 241124.2
Net AOV (INR): 1076.45

Walk through the result

The numerator sums net revenue over the whole accepted table because cancellations have already been assigned zero. The denominator explicitly selects non-cancelled orders. Keeping those choices visible makes the definition reviewable. Dividing by 100 is presentation only; the underlying calculation retains integer minor units. The assertions verify three business invariants independently of the printed totals. A returned order can remain in the denominator while contributing zero to revenue, so filtering to positive revenue would silently define a different AOV.

Common mistakes and diagnosis

Do not label this metric “profit”; no cost data exists. Do not call the count “customers”; customers can place several orders. Do not silently remove returns because the result looks healthier. If two dashboards disagree, compare date boundaries, statuses, refunds, currency units, and denominators before looking for a pandas bug. A metric name without these rules is an incomplete specification.

Practice assignment

Calculate cancellation share among all accepted orders. Then calculate revenue per identified purchasing customer, excluding cancellations and missing customer IDs. State why those two denominators differ. Write one sentence naming a decision this dataset cannot support.

Worked solution and explanation

Add the following code below the worked example, or run the matching file in the solutions folder. Compare the result with the business definition before trusting a passing assertion.

cancel_share = orders['status'].eq('cancelled').mean()
identified = eligible.dropna(subset=['customer_id'])
per_customer = identified['net_paise'].sum() / identified['customer_id'].nunique() / 100
assert 0 <= cancel_share <= 1
print('Cancellation share:', round(float(cancel_share), 4))
print('Revenue / identified customer (INR):', round(float(per_customer), 2))

Check your understanding

Why can a fully refunded order lower AOV even when it contributes no revenue?

Answer guide

Our contract counts every non-cancelled order, including fully returned orders. A full refund reduces its net revenue to zero but does not remove the order from that population. Changing the denominator to positive-revenue orders would answer a different question. Neither definition is universal; the important requirement is to name and apply the chosen contract consistently.

Reference and next step

Download the complete course kit: datasets, all examples, solutions, and capstone.

Return to the full Data Analysis with Python and pandas curriculum.

Progress is saved in this browser.