
Transform complex data into actionable insights
An end-to-end R analysis pipeline that transforms 525,461 raw transactional records into five production-ready charts and a certified monthly revenue summary, revealing performance patterns for a UK online retailer.
The Problem
The client held two years of online retail data in a single Excel file with 525,461 rows and no cleaning, no feature engineering, and no reporting structure. Returns were mixed with real sales, missing customer IDs inflated counts, and invalid price entries distorted every aggregate.
Credit note invoices starting with "C" were treated as regular sales, inflating revenue and order counts. They had to be identified and excluded before any analysis was valid.
110,855 missing values across the dataset. Customer ID nulls prevented any customer segmentation or cohort analysis, requiring targeted filtering before aggregation.
Zero-price rows (service or admin entries) and negative quantities (return lines) corrupted all revenue calculations. Explicit thresholds were required before any figure could be trusted.
The raw file had no revenue column, no month grouping, and no return flag. Every analysis dimension had to be built from scratch using feature engineering before a single chart could be produced.
Solution Architecture
The analysis follows a structured five-stage workflow written in a single R script. Every parameter is defined at the top so thresholds are easy to adjust. The pipeline runs reproducibly from a clean session with no manual intermediate steps.
Data Engineering
Every transformation was parameterised and applied in sequence. The script runs as a single block from the top, with no manual steps, producing certified outputs every time.
525,461 rows read from the source XLSX via readxl. Column names immediately converted to snake_case using janitor::clean_names().
Four derived columns added: invoice_date cast to Date, month floored to month start, year extracted, is_return flag for "C" invoices, and revenue calculated as price times quantity.
Four filters in sequence: exclude returns, drop missing customer IDs, enforce min_price of 0.01, enforce min_quantity of 1. Result: 407,650 valid sale rows retained.
Five group_by summarise pipelines built: revenue and orders by month, top 10 products, top 10 countries, monthly unique customers, and average order value per month.
Five publication-quality charts built with ggplot2, sharing a theme_sales() function from R/plot_theme.R. Axes formatted with currency and comma separators via the scales package.
Five PNG charts exported at print resolution (10x5 or 10x6 inches). Monthly revenue summary exported as revenue_summary.csv. All outputs fully reproducible by re-running from the top.
Deliverable
Each analysis was built as a standalone aggregation pipeline before being passed to ggplot2. The shared theme_sales() function ensures consistent typography, grid lines, and spacing across every chart.
Results
Top 5 Products by Revenue
| # | Product | Revenue |
|---|---|---|
| 01 | WHITE HANGING HEART T-LIGHT HOLDER | £151,624 |
| 02 | REGENCY CAKESTAND 3 TIER | £143,893 |
| 03 | Manual ⚠ possible miscoded entry | £98,561 |
| 04 | ASSORTED COLOUR BIRD ORNAMENT | £70,494 |
| 05 | JUMBO BAG RED RETROSPOT | £51,759 |
Technology