Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Online Sales Analysis

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.

Headline numbers

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%

Data cleaning

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.

Results

1 — Discounting does not drive volume

ρ = +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%+.

Discount vs quantity

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.

2 — Channels are indistinguishable

Online median 689.18 (n = 23,762) versus in-store 692.93 (n = 23,531), p = 0.30, effect size +0.006.

Channel comparison

Neither channel should be deprioritised on order value; they perform the same.

3 — No category differences

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.

Category comparison

4 — Priority does not track order value

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.

Priority spread

The priority label is not carrying information about order value, which is worth investigating operationally: it suggests the label is applied inconsistently.

5 — Returns are unrelated to payment method

χ² = 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%.

Returns by payment method

Method notes

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.

Dashboard

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.

Running it

pip install -r requirements.txt
python -m src.hypothesis_tests

Reads 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.

Structure

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

Limitations

  • 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.
  • ShippingCost is missing on 2,489 rows and treated as zero in TotalCost; 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.

About

This project explores key drivers of revenue and sales performance in an e-commerce environment. Using statistical hypothesis testing and exploratory data analysis, it evaluates the impact of discounts, sales channels, product categories, and payment methods on business outcomes.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages