21. Stats You Need for Data Work
21.4 Distributions and Skew
In short: Skew is the everyday word for “pulled to one side”.
Why. A histogram answers: are most orders small with a long right tail (festivals), or roughly balanced? Skew is the everyday word for “pulled to one side”.
What.
- Right-skewed (positive): long tail to the right — common for ₹ amounts (many small, few large).
- Left-skewed: long tail to the left — rarer in baskets; sometimes scores.
- Roughly symmetric: mean ≈ median.
You do not need formulas with cubes for this course. Compare mean vs median and look at a histogram.
How.
See skew without fear
- Compute mean and median.
- If mean ≫ median → suspect right skew (big ₹ tails).
- Plot
df["amount"].plot(kind="hist", bins=20)or seabornhistplot. - Split normal week vs Diwali window (e.g. 15–22 Oct) and compare.
- Write the insight in one sentence for the ops group.
Worked example A — Normal week vs Ganeshotsav window (fictional Nagpur).
import numpy as np
import pandas as pd
rng = np.random.default_rng(7)
normal = rng.integers(60, 160, size=80)
fest = np.concatenate([
rng.integers(70, 180, size=70),
rng.integers(400, 900, size=10), # mithai / decor spikes
])
def skew_story(arr, label):
s = pd.Series(arr)
print(label, "mean", round(s.mean(), 1), "median", s.median(),
"max", s.max())
skew_story(normal, "Nagpur normal week")
skew_story(fest, "Nagpur Ganeshotsav week")
What you should see. Festival week: mean climbs; median moves less; max jumps. Salman should not staff “average” — he should plan for a fat right tail on festival evenings.
Worked example B — Histogram in five lines.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
pd.Series(fest).plot(kind="hist", bins=15, ax=ax, edgecolor="black")
ax.set_xlabel("Order amount (₹)")
ax.set_ylabel("Orders")
ax.set_title("Nagpur fictional Ganeshotsav amounts")
fig.savefig("figures/nagpur_fest_hist.png", dpi=120, bbox_inches="tight")
plt.close()
Save the PNG for WhatsApp (Chapter 22). Do not paste the whole notebook.
Worked example C — Status mix is also a “distribution”.
status = pd.Series(
["Delivered"] * 50 + ["Cancelled"] * 6 + ["Returned"] * 4
)
print(status.value_counts(normalize=True).round(3))
Zoya reports: “Delivered 83%, Cancelled 10%, Returned 7% (fictional sample).” That categorical distribution matters as much as ₹ skew.