Statistical analysis of ~50,000 retail orders across online and in-store channels, with a Power BI dashboard over the same data.
Five stakeholder questions, all tested on the cleaned data. All five came back negative — the differences the business might expect are not there.
| # | Question | Result |
|---|---|---|
| 1 | Do bigger discounts drive bigger orders? | No — ρ = +0.0008, p = 0.87 |
| 2 | Does online out-earn in-store? | No — p = 0.30 |
| 3 | Does revenue differ by category? | No — p = 0.73 |
| 4 | Is revenue spread wider for high-priority orders? | No — CI includes zero |
| 5 | Is the return rate linked to payment method? | No — p = 0.63 |
A run of null results is a finding, not a failure: it says these five levers do not separate the business the way the operating assumptions suggest.
After cleaning (47,293 of 49,782 rows retained):
| Net revenue | 44.6M |
| Orders | 47,293 |
| Average order value | 943.77 |
| Return rate | 9.82% |
This is the part that changes the answers. The export is not clean, and the errors do not merely add noise — they invert a result.
| Issue | Rows | Why it matters |
|---|---|---|
Discount above 1.0 (up to 2.0) |
996 | A 200% discount makes NetRevenue negative |
Quantity ≤ 0 |
1,493 | Negative quantities flip the sign of any correlation |
UnitPrice ≤ 0 |
0 remaining | All such rows were already removed by the two rules above |
PaymentMethod spelled paypall |
16,505 | Normalised to PayPal |
5.0% of rows are dropped in total.
Test 1 is the clear example. On the raw export the discount–quantity correlation is ρ = −0.058 at p ≈ 1e-38 — apparently a strong, highly significant negative relationship, and previously reported as one. After removing the impossible discounts and negative quantities it is ρ = +0.0008 at p = 0.87: no relationship at all. The original finding was an artifact of the dirty rows, not a property of the business.
ρ = +0.0008, p = 0.87 (n = 47,293). Median order size is flat at 24–25 units across every discount bracket, while revenue falls steadily as discounts deepen — from 11.9M in the 0–10% bracket to 6.1M at 40%+.
Deeper discounting buys no additional volume here; it only reduces the revenue per order. On this evidence the discount ceiling could be lowered without losing units.
Online median 689.18 (n = 23,762) versus in-store 692.93 (n = 23,531), p = 0.30, effect size +0.006.
Neither channel should be deprioritised on order value; they perform the same.
Kruskal-Wallis H = 2.04, p = 0.73 across five categories. Medians span 680–708, and 0 of 10 category pairs differ once Bonferroni-corrected.
IQR(High) − IQR(Low) = 8.06, bootstrap 95% CI [−26.27, 42.17] — the interval includes zero. Medians are near-identical across Low, Medium and High.
The priority label is not carrying information about order value, which is worth investigating operationally: it suggests the label is applied inconsistently.
χ² = 0.93, dof = 2, p = 0.63, Cramér's V = 0.004. Return rates sit within 0.3 points of each other: Bank Transfer 10.00%, PayPal 9.79%, Credit Card 9.68%.
Test 4 tests IQR, not variance. The question is about spread as IQR, so it is answered with a bootstrap CI on the difference in IQR. Levene's test compares variance, which on right-skewed revenue is dominated by a handful of large orders and answers a different question.
Test 3 corrects for multiple comparisons. Five categories give 10 pairwise tests; uncorrected, one would reach p < 0.05 by chance about 40% of the time.
Effect sizes accompany p-values. At n ≈ 47,000 significance is cheap, so rank-biserial correlation and Cramér's V are reported. Test 1 also notes that |ρ| < 0.05 means nothing practically meaningful regardless of the p-value.
Figures trim the top 5% for legibility; every statistic uses the full cleaned data.
Online Sales.pbix, four pages. Note that its figures are computed on the
raw export, so they differ slightly from the cleaned numbers above (43.51M
revenue, 50K orders, 9.83% return rate, AOV 874.04) and it still shows the
paypall spelling and discounts running past 1.0 on the Discount vs Quantity
scatter.
Page 1 — Overview. Revenue, orders, return rate and AOV, with revenue by month, by category, and mapped by country.
Page 2 — Channel and geography. Online versus in-store revenue, revenue by day of week, top 10 countries, and the payment-method split (roughly even thirds).
Page 3 — Returns and shipping. Return rate by category, by payment method and by country, average shipping cost by provider, and a warehouse × provider cost matrix (all providers cluster near 17.4–17.6).
Page 4 — Discount and priority. Discount versus quantity scattered by category, average discount by category, revenue and orders by priority, and the discount-bracket breakdown that shows revenue falling as discounts deepen.
pip install -r requirements.txt
python -m src.hypothesis_testsReads online_sales_dataset.csv if present, otherwise falls back to the
committed online_sales_added_columns.csv, which holds the same rows plus the
derived columns. Derived columns are always recomputed, so the cleaning rules
apply either way. Seeded with RANDOM_STATE = 42; the bootstrap reproduces
exactly.
src/preprocessing.py loading, cleaning, derived columns
src/hypothesis_tests.py the five tests and their figures
figures/ generated output, committed
Online Sales.pbix Power BI dashboard
online_sales_added_columns.csv full data with derived columns
requirements.txt pinned versions
- Null results are not proof of no effect. These tests rule out differences large enough to matter at this sample size; a small real effect could still exist.
- Observational data. Discounts were not assigned randomly, so the flat discount–quantity relationship describes what happened, not what would happen if pricing changed.
- No cost or margin data, so "revenue eroded by discounting" is lost revenue, not lost profit.
ShippingCostis missing on 2,489 rows and treated as zero inTotalCost; it is not used by any of the five tests.- One export, no time-series validation. Yearly slicers exist in the dashboard, but none of the tests here model change over time.




