Projects
Five projects, ordered by what they ask of the data: first understand what's happening, then predict what will, then recommend what to do about it.
Do Listings Lie? How Airbnb Language Predicts Price
Text analytics across 61,521 listings in 16 cities
Premium words like “luxury” and “stunning” predict nightly price three times more strongly than generic positive sentiment.
Imagine two flats on Airbnb that are genuinely identical: same neighbourhood, same number of bedrooms, same square footage, same amenities, same guest rating. One is described as a "stunning luxury apartment." The other is described as a "nice place to stay." Does the first one charge more? And if so, is that because the property is actually better, or purely because of how it was written up?
To answer that, we took 261,894 Airbnb listings, cleaned them down to 61,521 across 16 English-speaking cities, and tested how much of the nightly price could be explained by the description text alone, separately from the physical facts of the property.
Two things stood out. First, being generically positive barely mattered: a broad "positivity score" of the description had almost no relationship with price. But specific premium words like "luxury," "stunning," and "breathtaking" had a relationship three times stronger. In other words, sounding enthusiastic is worthless; sounding expensive is not.
Second, and more importantly, that premium-language effect survived when we controlled for the property itself, comparing listings with the same size, type, location, and rating. So the effect isn't just "nicer flats get described more nicely." The language carries its own price premium on top of what the property justifies, which is exactly the two-identical-flats scenario above.
Why it matters
The words a host chooses are worth money. Writing "luxury apartment with stunning views" instead of "nice flat, great location" is associated with a real price difference, even when the two properties are otherwise the same. For hosts, that makes the listing description a lever worth pulling. For Airbnb, it's a way to spot listings that oversell themselves.
R² on a 20% held-out test set: how much price variance each model explains.
Click to view the full report, methodology, data and code+
Dataset: Public Airbnb listings dataset, 16 English-speaking cities
Tools: R · glmnet (LASSO) · tidytext · topicmodels (LDA) · sentimentr
- Cleaned 261,894 listings to 61,521 across 16 cities; log-transformed price for near-normality
- Metadata-only LASSO benchmark (8 property variables): R² = 0.569
- Text-only TF-IDF LASSO (1,415 selected words): R² = 0.446
- Combined model (metadata + TF-IDF + LDA topics): R² = 0.660, a 9-point lift over metadata alone
- Trained on London (11,394 listings), tested cross-city generalisation on 15 held-out cities
Customer Segmentation & Heterogeneous Churn Dynamics
K-Prototypes clustering + segment-specific regression on 5,329 e-commerce customers
In most customer segments, ordering more predicts a higher chance of churning. In the highest-risk segment, it's the opposite: ordering more predicts they'll stay.
Most companies build one churn model for their whole customer base and apply one retention strategy to everyone. This project asked whether that's actually safe: do different types of customers leave for different reasons?
Starting with 5,329 e-commerce customers, of whom about 17% had churned, we first grouped customers by how they actually behave (how long they'd been around, what they bought, how often, how much they used coupons) rather than by who they are demographically. Four distinct groups fell out of that.
The gap between groups was large. The riskiest group churned at 27.9%, more than three times the safest group's 8.5%. The single biggest driver was simply how new someone was: customers in their first three months churned at 41.9%, while customers past two years churned at essentially zero. Practically, this means retention money is almost always best spent on the first few months of a customer's life.
The more surprising result came from modelling each group separately instead of all together. In most groups, ordering more and using more coupons predicted a higher chance of leaving, which fits a picture of people who show up for a promotion and disappear afterwards. But in the newest, highest-risk group, that flipped: there, more orders predicted people were more likely to stay. Same behaviour, opposite meaning, depending on who's doing it. A single company-wide model averages those two opposite effects together and effectively hides both.
Why it matters
A customer ordering a lot is usually read as a happy customer. In this data, that was often wrong: for most people, a burst of orders meant they were chasing discounts and would leave once the discounts stopped. So a business that rewards its heaviest orderers with more coupons could be spending money on exactly the customers it's about to lose anyway, while ignoring the newer customers where more orders genuinely does mean they're sticking around.
Churn rate by segment. The highest-risk group churns 3.3x more than the safest one, and behaves differently, not just worse.
Click to view the full report, methodology, data and code+
Dataset: E-commerce Customer Churn Analysis and Prediction dataset (Kaggle, Ankit Verma, 2021)
Tools: R · K-Prototypes clustering · clustMixType · Logistic regression
- 5,329 customers, 20 variables, from the Kaggle E-commerce Customer Churn dataset
- K-Prototypes clustering (mixed numeric and categorical features) identified 4 behaviourally distinct segments
- Cluster 3 ("High-Risk New Customers"): 27.9% churn, 5.25-month average tenure, concentrated in one-off mobile phone purchases
- Cluster 4 ("Loyal Customers"): 8.5% churn, 16.6-month average tenure, concentrated in repeat grocery purchases
- Segment-specific logistic regressions outperformed a single global model: AUC 0.863 to 0.872, F1 0.543 to 0.556, recall 0.432 to 0.463
- Order count and coupon usage predict higher churn in most segments but reverse sign in Cluster 3
Psychological Distress & Physical Multimorbidity in England
Negative binomial regression on Health Survey for England 2022 (n = 4,735)
Each one-point rise in psychological distress predicts a 9.7% increase in physical health conditions. That effect is statistically identical in the richest and poorest neighbourhoods.
It's well established that people in deprived areas have worse physical health, and that mental distress and physical illness tend to go together. The open question was how those two interact. Does deprivation make distress hit harder, or do they simply stack on top of each other?
This matters practically because the two answers lead to different NHS policies. If deprivation amplifies the effect, you target mental health resources at deprived areas. If the effects are just additive, you screen everyone.
Using survey data from 4,735 adults across England, we measured psychological distress and counted each person's long-term physical conditions, then adjusted for age, sex, income, education, smoking, drinking, and region so we weren't just picking up those factors instead.
Distress and physical illness were clearly linked: each one-point increase in someone's distress score came with roughly 9.7% more physical conditions, and that held up firmly across every version of the model we tried. Living in the most deprived areas independently added about 25% more conditions.
The key test was whether those two effects multiply. They don't. When we explicitly checked whether distress hits harder in deprived areas, the result was flatly insignificant. Both raise physical illness, but they do so independently, so the extra risk carried by a distressed person is much the same regardless of where they live.
Why it matters
You'd expect mental distress to be especially damaging for people in poorer areas, so that's where you'd concentrate mental health screening. The data says otherwise. People in deprived areas do carry more physical illness overall, but distress adds the same amount of extra illness whether you're rich or poor. That points towards checking mental health across all patients in physical care, not just the ones from deprived postcodes.
Predicted physical condition count by distress score. The lines run parallel, not divergent: deprivation shifts the baseline but not the slope.
Click to view the full report, methodology, data and code+
Dataset: Health Survey for England 2022 (UK Data Service, Study Number 9469)
Tools: Python · statsmodels · Negative binomial GLM · Survey weighting
- Analytical sample: 4,735 adults (complete-case), Health Survey for England 2022, UKDS SN 9469
- Outcome overdispersed (variance/mean = 1.53), so negative binomial was preferred over Poisson (LR = 122.68, p < 0.001)
- 4 nested models: GHQ-12 only, then + demographics, then + full controls, then + GHQ×IMD interaction
- Preferred spec (Model 3): IRR = 1.097 for GHQ-12, robust to OLS, logistic, and BMI-adjusted checks
- GHQ×IMD interaction jointly insignificant (χ²(4) = 1.21, p = 0.877), no effect modification by deprivation
Heat Smart Orkney: The Commercial Case for Demand Response
Curtailment modelling and commercial viability analysis for Kaluza
A residential demand-response scheme would absorb less than 1% of Orkney's curtailed wind energy. It would still turn an annual profit of £151,000 at scale.
Orkney generates far more wind power than it can use or export. The cable connecting it to the mainland fills up, so turbines get switched down and roughly 23% of the potential electricity, about 450,000 MWh a year, is simply never generated. Kaluza wanted to know whether they could make money from that by paying households to run smart storage heaters at exactly the moments when the wind power would otherwise be wasted.
To answer that, we used several years of minute-by-minute turbine data to work out precisely when and how much energy was being lost, then built a financial model of what it would cost to install the devices in homes and what the scheme would earn from the network operator and wind farm owners.
The first finding was a disappointing one. Even in the best realistic case, with about a third of eligible households signed up, the scheme would soak up only around 0.75% of the wasted energy. Home heating is just too small to absorb an oversupply on that scale, so anyone pitching this as a solution to curtailment would be overpromising.
The second finding is why the project still ended in a recommendation to proceed. The money doesn't come from the energy saved, it comes from being paid to provide flexibility to the grid. That changes the economics completely: the scheme breaks even at 15% household sign-up and earns around £151,000 a year at 30%. So it's a viable business even though its environmental impact is small, and the recommendation was to roll it out in phases, but only after securing a long-term flexibility contract, since that payment is what the entire business case rests on.
Why it matters
The honest answer to the client's question was "this won't fix the problem, but you should still do it." The scheme can't meaningfully dent the wasted wind energy, so selling it as an environmental fix would set it up to fail. It does make money though, and it makes money at a scale that's realistically achievable. Being clear about which of those two things is true mattered more than making the project sound impressive.
Base case: SSEN flexibility payment £250/MWh, wind-farm fee £25/MWh. Break-even (highlighted) lands at 15% penetration.
Click to view the full report, methodology, data and code+
Dataset: Rousay turbine telemetry (2015-2018) and Orkney residential demand data
Tools: Python · pandas · Power curve modelling · Financial and sensitivity modelling
- Cleaned turbine telemetry (2.63 years, 1-min intervals) to classify wind-limited, capacity-limited, and demand-limited (curtailed) states
- Annual curtailment: ~450,431 MWh/yr (23.1%), of which 268,146 MWh/yr (59.5%) is DR-addressable
- Sense-checked against published Rousay turbine curtailment data (model within 1.07× of implied fleet total)
- Household financial model: device cost, 12-year lifetime, SSEN flexibility payment (£250/MWh base case), wind-farm service fee (£25/MWh)
- Break-even at 15% penetration (£36,590/yr profit); £151,112/yr profit and £283,459 cumulative cash flow by Year 5 at 30% penetration
- Sensitivity analysis: SSEN flexibility price is the dominant driver of viability, ahead of wind-farm fees or subsidy
HBS Data Analytics Simulation: Brand Strategy & Market Forecasting
Individual project, 8-year competitive market simulation
Blue was the weakest of four detergent brands, flat at 9-11% market share for four years. Repositioning it on data instead of price took market share to 14.1% and cumulative profit to $242.0M by Year 8.
This was a competitive simulation where four detergent brands fight for the same market over eight years. I inherited Blue, the weakest of the four: stuck at 9-11% market share, priced in an awkward middle where it was neither the cheap option nor the premium one, and giving customers no clear reason to pick it.
Rather than cutting the price, which would have started a race to the bottom against a competitor already undercutting everyone, I used the platform's demand data to find an unoccupied position. The data showed odour elimination was the most in-demand product attribute and pods were the fastest-growing format, so Blue was rebuilt around both, with marketing spend concentrated on the specific regions and customer groups the data favoured instead of spread evenly.
The strategy worked. Market share rose from 11% to 14.1% and cumulative profit more than tripled to $242.0M. But the part of this project I find more valuable is what went wrong alongside it.
In year five, the repositioning worked far better than expected and demand jumped. I'd set production based on the previous year's sales, so we sold out and left roughly $104M of revenue on the table, then took a further hit when customers who couldn't find the product complained publicly and suppressed the following year's demand too.
Going back afterwards and recalculating what better decisions would have earned, roughly $132M of losses across the simulation were avoidable. Almost all of it traced to one root cause: I made each decision on its own, in sequence, when production, pricing, formulation, and targeting all feed into each other and needed to be decided together.
Why it matters
The lesson here wasn't the market share win, it was how the losses happened. Every major mistake came from the same habit: setting this year's number by nudging last year's number, instead of asking what this year's strategy would actually cause. Deciding how much to produce before thinking through what the new marketing and pricing would do to demand is how you end up selling out and losing $104M of revenue you'd already won.
Blue's market share by year. Grey bars are the inherited baseline (Years 1 and 4); teal bars are the years I made the decisions.
Click to view the full report, methodology, data and code+
Dataset: Simulation platform data (Years 1-8, decisions for Years 5-8)
Tools: K-W Vision simulation platform · Scenario analysis · Newsvendor model · Kotler STP & Keller CBBE frameworks
- 8-year market simulation (Years 1-4 inherited, Years 5-8 player-controlled) against 3 competitor brands
- Pre-game analysis of platform data identified odour elimination and Pods formulation as the highest-demand positioning
- Held price at $7.00 through Years 5-7 despite a competitor price war, based on price-bracket demand data ($5-7 bracket 48% larger than $7-9)
- Year 5 production, anchored to Year 4 demand, caused a 14.9M-unit stockout and $104M in foregone revenue
- Post-hoc counterfactual analysis quantified ~$132M in avoidable losses from treating annual decisions sequentially rather than as one integrated problem