⚙️ Setup¶
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
NAVY="#0a1230"; INK="#1a2138"; INK_SOFT="#4a5578"
CYAN="#0891b2"; PURPLE="#7c3aed"; AMBER="#d97706"; GREEN="#059669"; PINK="#db2777"; BLUE="#2563eb"; GRID="#e6e9f2"
plt.rcParams.update({
"figure.facecolor":"white","axes.facecolor":"white","figure.dpi":110,"font.size":11,
"axes.edgecolor":GRID,"axes.linewidth":1.2,"axes.grid":True,"grid.color":GRID,"axes.axisbelow":True,
"axes.spines.top":False,"axes.spines.right":False,"axes.titlesize":14,"axes.titleweight":"bold","axes.titlecolor":INK,
"axes.labelcolor":INK_SOFT,"xtick.color":INK_SOFT,"ytick.color":INK_SOFT,"legend.frameon":False})
print("✅ Ready.")
✅ Ready.
answer = pd.DataFrame({
"variable":["age","eye color","number of siblings","temperature","T-shirt size"],
"big type":["Quantitative","Qualitative","Quantitative","Quantitative","Qualitative"],
"subtype": ["Continuous","Nominal","Discrete","Continuous","Ordinal"],
"why": ["measured, any value","categories, no order","counted whole numbers",
"measured, any value","categories WITH an order S<M<L"],
})
answer
| variable | big type | subtype | why | |
|---|---|---|---|---|
| 0 | age | Quantitative | Continuous | measured, any value |
| 1 | eye color | Qualitative | Nominal | categories, no order |
| 2 | number of siblings | Quantitative | Discrete | counted whole numbers |
| 3 | temperature | Quantitative | Continuous | measured, any value |
| 4 | T-shirt size | Qualitative | Ordinal | categories WITH an order S<M<L |
Answer: the trick is two questions, is it a number you can do math on? (quantitative vs qualitative), then countable or measurable? / ordered or not? T-shirt size is the classic "looks like a category but has order" → ordinal.
customers = pd.DataFrame({
"city": ["Lagos","Cairo","Lagos","Nairobi"],
"age": [25, 41, 33, 29],
"plan": ["Free","Pro","Pro","Free"],
"monthly_$": [0.0, 12.99, 12.99, 0.0],
})
qualitative = [c for c in customers.columns if customers[c].dtype == "object"]
quantitative = [c for c in customers.columns if customers[c].dtype != "object"]
print("Qualitative (categories):", qualitative)
print("Quantitative (numbers) :", quantitative)
Qualitative (categories): [] Quantitative (numbers) : ['city', 'age', 'plan', 'monthly_$']
Answer: Qualitative → city, plan (text categories). Quantitative → age, monthly_$ (numbers). A quick first pass: pandas stores text categories as the object dtype.
items = {
"cars in a parking lot": "Discrete (counted, whole numbers)",
"weight of a parcel": "Continuous (measured, any value)",
"goals scored": "Discrete (counted, whole numbers)",
"time to run 5 km": "Continuous (measured, any value)",
}
for k, v in items.items():
print(f"{k:<24} -> {v}")
cars in a parking lot -> Discrete (counted, whole numbers) weight of a parcel -> Continuous (measured, any value) goals scored -> Discrete (counted, whole numbers) time to run 5 km -> Continuous (measured, any value)
Answer: if you count it (cars, goals) it's discrete; if you measure it (weight, time) it's continuous. A handy test: continuous values can always have more decimal places.
roles = {
"Independent variable (cause)": "amount of fertilizer",
"Dependent variable (effect)": "plant height",
"Possible confounder": "sunlight (affects growth AND may vary by plot)",
}
for k, v in roles.items():
print(f"{k:<32}: {v}")
Independent variable (cause) : amount of fertilizer Dependent variable (effect) : plant height Possible confounder : sunlight (affects growth AND may vary by plot)
Answer: IV = fertilizer (what we change), DV = plant height (what we measure). A confounder like sunlight or watering could influence height too, so a fair experiment must hold those constant. IV → DV, with confounders controlled.