Practice Set: Applied Python for DS
Explore how to identify and fix common errors in pandas pipelines that affect data metrics, including cleaning account and payment data, managing joins without duplication, and calculating accurate rolling payer rates. Learn validation checks, handling missing data, and documenting limitations to ensure reliable Python-based analysis for data science interviews.
We'll cover the following...
- Problem 1: Normalizing plan names in a filtered frame
- Solution
- Problem 2: Cleaning sessions with a bare dropna
- Solution
- Problem 3: Converting raw payment amounts
- Solution
- Problem 4: Revenue inflated by a merge
- Solution
- Problem 5: Counting active accounts by day
- Solution
- Problem 6: Rolling seven-day payer rate
- Solution
- Check yourself
A pandas pipeline can produce incorrect metrics even when the code executes successfully. Common causes include duplicate account_id values, invalid dates in paid_at, and unexpected changes to the denominator after a merge.
The exercises use four pandas DataFrames defined directly in the code: accounts, sessions, events, and payments. For each problem, identify the minimal correction, verify the resulting metric, explain one validation check, and document one limitation.
The six problems progress from data cleaning (Problems 1–3) to data granularity and joins (Problems 4–5), followed by a complete rolling-metric pipeline (Problem 6). Each problem uses a separate, simplified version of the relevant tables. Attempt each problem independently before reviewing the hints and worked solutions.
The relationships are deliberately uneven:
accountscontains one row peraccount_id.sessionscontains one row persession_idand links toaccount_id.eventscontains many rows persession_id.paymentscontains many rows peraccount_id, withpaid_atstored as raw text.
Before writing code, state the grain of the requested output. A daily payer-rate table has one row per calendar day. A payment table has one row per payment. Confusing those grains is enough to make a plausible result invalid.
Problems 1 through 3 isolate cleaning failures. Each snippet is near-correct, so the useful move is to find the first operation that changes the intended data rather than rewriting the whole pipeline.
Problem 1: Normalizing plan names in a filtered frame
Scenario: A teammate normalizes plan names for US accounts:
us = accounts[accounts[“country”] == “US”] then us[“plan”] = us[“plan”].str.strip().str.lower()
Afterward, accounts[“plan”] still contains “Pro ” and “ pro”. Predict why, and give the smallest fix.
Question: Why does the original frame still contain the old plan names, and what is the smallest fix?
Solution
us is a filtered copy, so the write never reaches accounts (pandas 2 shows a SettingWithCopyWarning; pandas 3 shows nothing, which is why you check accounts afterward). Assign with accounts.loc[mask_us, “plan”] = accounts.loc[mask_us, “plan”].str.strip().str.lower(). The check is to print accounts[“plan”] and confirm that accounts.shape is unchanged.
Problem 2: Cleaning sessions with a bare dropna
Scenario: sessions has 4 rows. One has a missing account_id, and two have a missing optional referrer. The count of sessions by account comes out as 1. Find the first consequential bug.
sessions = pd.DataFrame({"session_id": ["s1", "s2", "s3", "s4"],"account_id": [101, 101, 103, None],"referrer": [None, "google", None, "newsletter"],"device": ["ios", "web", "android", "web"],})sessions_clean = sessions.dropna()
Question: What is the first consequential bug in the cleaning line, and what is the smallest fix?
Solution
A bare dropna() drops any row with any missing value, so two valid sessions vanish because referrer is empty. Use sessions.dropna(subset=[“account_id”]), which keeps 3 rows, and report the one keyless row as an exclusion.
Problem 3: Converting raw payment amounts
Scenario: payments[“amount”] = payments[“amount_raw”].astype(float) fails on [“19.99”, “free”, “ 8.00 ”, “20”, None]. What happens, and what should we do instead?
...