Skip to content
Data Science

END-TO-END DATA SCIENCE · E-COMMERCE OPERATIONS

Aug 2026

Predicting late-delivery risk before it affects the customer

I transformed seven raw marketplace tables into validated analytical cohorts, an adjusted statistical study, a temporally backtested prediction model, and a reproducible batch-scoring workflow.

94,988
Eligible orders modelled
review-independent, delivered, single-seller
18×
Adjusted odds of dissatisfaction when late
dissatisfaction model with seller-clustered uncertainty
2.36×
Lift in the highest-risk 10%
23.6% of held-out late deliveries captured
27
Automated tests
including a seven-table integration test

What I built

I designed the work as one traceable path from source data to a score another system can consume. Each stage leaves an auditable table, metric, test, or model artifact behind.

  1. 01

    Data foundation

    7 raw tables → validated analysis and modelling cohorts

  2. 02

    Statistical study

    Adjusted dissatisfaction analysis with seller-clustered uncertainty

  3. 03

    Prediction pipeline

    Checkout-time features → baseline and model comparison

  4. 04

    Temporal evaluation

    Untouched holdout → six monthly backtests

  5. 05

    Decision layer

    Top-k capture → intervention economics

  6. 06

    Delivery artifact

    Saved model, metadata, and batch-scoring CLI

Audit trail and project artifacts
  • Cohorts: a row-count audit separates the review-dependent dissatisfaction study from the review-independent delivery model.
  • Evaluation: machine-readable outputs store validation comparisons, bootstrap intervals, risk bands, rolling backtests, calibration, drift, and intervention scenarios.
  • Deployment artifact: the fitted preprocessing and logistic model are saved together with feature-order metadata and a two-row scoring contract example.
  • Documentation: the repository explains reproduction; the model card states intended use, failure modes, monitoring, and retraining expectations.

Two questions, two cohorts

Olist connects marketplace sellers to customers. Every delivered order carries an internal seller handoff deadline and a customer-facing promised delivery date. The project asks two related questions: which missed deadline is most strongly associated with dissatisfaction, and can late customer delivery be ranked from information available at checkout?

Those questions require different populations and are kept separate throughout.

Dissatisfaction analysis

93,306

Reviewed orders used to study 1–2-star dissatisfaction and deadline outcomes. Review availability is required here.

Late-delivery modeling

94,988

Eligible delivered orders used to model late delivery. Reviews do not determine membership in this cohort.

Starting from 99,441 raw orders, the pipeline validates keys and schemas, resolves reviews, aggregates order items, checks timestamp coherence, and restricts the main populations to delivered single-seller orders with interpretable delivery timestamps.

What drives dissatisfaction?

Dissatisfaction is defined as a 1–2-star review. Splitting reviewed orders by the deadlines they met reveals a sharp operational divide.

Dissatisfaction by fulfilment outcome

Dissatisfaction rate by fulfilment outcome

Dissatisfaction is 8.2% when both deadlines are met and 13.2% when a late seller handoff is recovered before delivery. Once the customer-facing promise is missed, it rises to 62–63% whether the seller handoff was on time or late.

Show the numbers
Dissatisfaction by fulfilment outcomeDissatisfaction rate by Fulfilment outcome
Fulfilment outcomeDissatisfied (1-2 star)
Both deadlines met8.2%
Late handoff, on-time delivery13.2%
On-time handoff, late delivery62.1%
Both deadlines missed63.1%

After adjusting for order size, price, freight, product category, customer state, and seller-clustered uncertainty across 2,935 sellers, the pattern remains. A late handoff recovered before delivery carries 1.52× the odds of dissatisfaction (95% CI 1.36–1.70). Late customer delivery carries 18.13× (16.49–19.94), and missing both deadlines carries 19.58× (17.32–22.14).

Statistical design and sensitivity checks

The analysis reports Wilson intervals for outcome rates, a chi-square association test (Cramér's V 0.413), and an adjusted binomial logistic model with standard errors clustered by seller. The model includes order composition, economics, category, geography, and deadline outcome.

The result survives alternative definitions. With only 1-star reviews flagged, late-delivery groups are about 9.2× baseline; with 1–3-star reviews flagged, they remain about 4.6× baseline. The magnitude changes, but the direction does not.

Can risk be ranked at checkout?

The prediction task uses only information available when an order is placed: composition, price and freight, weight, promised window, geography, and cyclical purchase timing. Actual handoff, delivery, and review fields are prohibited by the feature contract.

Models are selected on an intermediate chronological validation period rather than a random split.

Validation PR-AUC by candidate model

PR-AUC by validation candidate

The full logistic model reaches 0.199 PR-AUC, compared with 0.071 for the prevalence baseline, 0.069 for the promised-window-only baseline, and 0.164 for gradient boosting.

Show the numbers
Validation PR-AUC by candidate modelPR-AUC by Validation candidate
Validation candidateValidation PR-AUC
Prevalence baseline0.071
Promised-window only0.069
Full logistic regression0.199
Gradient boosting0.164

Logistic regression generalized better than the more flexible model. Gradient boosting reached 0.832 training ROC-AUC but only 0.650 on validation; logistic regression moved from 0.739 to 0.731 and was selected before the final holdout was opened.

Leakage and uncertainty controls

Preprocessing is fitted on training data only and serialized with the selected model. The latest 20% of eligible orders—18,998 orders from May 24 to August 29, 2018—form the untouched holdout. Reported uncertainty comes from 500 bootstrap resamples: holdout ROC-AUC 0.698–0.733, PR-AUC 0.070–0.094, capture 20.6–26.6%, and lift 2.06–2.66× at 95% confidence.

Does the model hold up over time?

A single holdout can conceal changes inside the period. I therefore added six expanding-window evaluations, each trained only on data available before the month being scored.

Late-delivery ranking performance varies by month

Monthly PR-AUC by evaluation month

The full model has the best PR-AUC in five of six monthly comparisons. In August, the promised-window-only baseline scores 0.167 while the full model falls to 0.087.

Show the numbers
Late-delivery ranking performance varies by monthMonthly PR-AUC by Evaluation month
Evaluation monthPrevalence baselinePromised-window onlyFull logistic model
2018-030.1920.1650.359
2018-040.0460.0410.192
2018-050.0670.0780.156
2018-060.0120.0180.092
2018-070.0340.060.086
2018-080.0630.1670.087

The full model's monthly ROC-AUC ranges from 0.603 to 0.794. Its loss to the promise-only baseline in August is not a footnote: it shows that the relationship between checkout features, Olist's promise policy, and late delivery changes over time. Monitoring and recalibration are requirements for any operational use.

How to read the rolling test

March through August 2018 are evaluated one month at a time. The training window expands through the end of the previous month; no future labels enter fitting or preprocessing. Each month compares the full logistic model against the same prevalence and promised-window-only baselines used during model selection.

What is the model actually learning?

Held-out permutation importance makes the model's dependence on existing policy visible.

Held-out permutation importance

Drop in held-out ROC-AUC when shuffled by feature

Shuffling the promised delivery window reduces ROC-AUC by 0.273. Every other feature changes it by less than 0.004 in the positive direction, while several features have negative held-out importance.

Show the numbers
Held-out permutation importanceDrop in held-out ROC-AUC when shuffled by Feature
FeatureROC-AUC drop when shuffled
Promised window0.273
Purchase month (cos)0.003
Order price (log)0.003
Total weight0.001
Purchase hour (cos)0.001
Purchase hour (sin)0.001
Item count0
Customer state-0
Purchase day (cos)-0.001
Purchase day (sin)-0.001
Freight value-0.002
Freight ratio-0.003
Purchase month (sin)-0.008
Distance (km)-0.012
Same state-0.034

The promised window is Olist's own estimate, not an independent measurement of fulfilment capacity. The full feature set clearly beats the promise-only ablation on validation, so there is incremental ranking signal; however, the dominant held-out contribution still reflects Olist's changing promise-setting policy.

Predicted versus observed late-delivery risk

Late-delivery rate by held-out risk band (1 = lowest)

Risk generally rises across held-out bands, but calibration is imperfect. The top band averages 13.7% predicted risk versus 8.4% observed risk.

Show the numbers
Predicted versus observed late-delivery riskLate-delivery rate by Held-out risk band (1 = lowest)
Held-out risk band (1 = lowest)Actual late rateMean predicted risk
10.5%0.5%
20.7%1.1%
31.2%1.6%
41.3%2.1%
52.3%2.6%
63.3%3.3%
75.6%4.0%
86.7%5.1%
95.4%7.1%
108.4%13.7%

The holdout Brier score is 0.0338 and expected calibration error is 1.21 percentage points. The model is more defensible for ranking limited outreach capacity than for treating raw scores as stable probabilities.

Drift changes the question

Monthly late-delivery prevalence

Late-delivery rate by purchase month

Prevalence spikes to 18.9% in March 2018, falls to 1.2% in June, then rises again. Training, validation, and holdout prevalence are 7.85%, 7.07%, and 3.54%, respectively.

Show the numbers
Monthly late-delivery prevalenceLate-delivery rate by Purchase month
Purchase monthLate-delivery rate
2016-100.8%
2017-013.0%
2017-022.6%
2017-034.5%
2017-046.4%
2017-052.8%
2017-063.0%
2017-072.8%
2017-082.9%
2017-094.4%
2017-104.1%
2017-1112.4%
2017-127.4%
2018-015.7%
2018-0214.0%
2018-0318.9%
2018-044.5%
2018-056.6%
2018-061.2%
2018-073.4%
2018-086.3%

The unusually low June rate coincides with a wider median promised window, but that window narrows again in July and August while lateness rises. The target captures both fulfilment performance and a moving promise policy.

Monitoring plan

Monthly monitoring should track prevalence, PR-AUC, top-k capture, calibration, feature missingness, and the promised-window distribution. A recent labeled window should be used for recalibration before probabilities drive cost-based decisions, and temporal validation should be repeated before a replacement model is accepted.

When is intervention worth it?

Ranking performance matters only if it supports a decision. The repository turns top-k capture into a replaceable scenario with 25% intervention effectiveness, 30 cost units per late delivery, and 1 unit per intervention.

Expected intervention value by targeting capacity

Expected net value (scenario units) by share of held-out orders targeted

Under the stated assumptions, targeting the highest-risk 1% produces +20 expected value units. Wider 5%, 10%, and 20% programs produce −162.5, −707.5, and −1,842.5 units.

Show the numbers
Expected intervention value by targeting capacityExpected net value (scenario units) by Share of held-out orders targeted
Share of held-out orders targetedExpected net value
1%20
5%-162.5
10%-707.5
20%-1,842.5
How the scenario is calculated

For each capacity, expected prevented late deliveries equal captured late deliveries multiplied by 25%. Avoided cost equals that result multiplied by 30; program cost equals targeted orders multiplied by 1. Net value is avoided cost minus program cost. The output also reports the break-even intervention cost at each capacity.

How the work is made reproducible

The analysis is packaged as software rather than a one-off notebook. The repository makes the data contract, transformations, evaluation, saved artifact, and generated evidence independently inspectable.

  • Modular Python package
  • Separate analysis and modelling cohorts
  • Leakage-safe preprocessing fitted on training data only
  • Saved model and adjacent metadata
  • Batch-scoring CLI with an explicit input contract
  • 27 automated tests
  • Seven-table integration test
  • GitHub Actions continuous integration
  • Pinned dependency lockfile
  • Checksum-verified data downloader
  • Model card covering use, limits, and monitoring
  • Machine-readable metrics and output tables
Reproduce, test, and score

The locked Python 3.12 environment installs the package in editable mode. The olist-delivery entry point rebuilds the processed cohorts, metrics, tables, figures, saved joblib pipeline, and JSON metadata. pytest runs the 27 tests in GitHub Actions on pushes and pull requests. After fitting, olist-score validates an engineered checkout-time CSV against the saved feature contract and writes order-level risk scores.

The downloader verifies checksums for all seven required source files before the pipeline runs. Generated CSV and JSON outputs let the claims on this page be audited without reading plots.

Data-quality appendix: the multi-seller anomaly

Olist records one customer-delivery timestamp per order even when an order is split across multiple sellers and parcels. That makes seller-level handoff and parcel completion ambiguous, so the main analysis is restricted to single-seller orders and the excluded population is audited separately.

The anomaly is substantial: two-seller orders show 46.6% dissatisfaction but only 1.0% recorded lateness, compared with 12.2% and 6.7% for single-seller orders. Their median promised window is only one day longer (25 versus 24 days), and reviews created before recorded delivery are less common (1.1% versus 5.1%), not more.

Population audit

The modelling flow moves from 99,441 raw orders to 96,478 delivered orders, then checks complete and coherent timelines, usable items, and seller count before reaching 94,988 eligible modelling orders. Only after that are usable reviews required, yielding the 93,306-order dissatisfaction cohort. Multi-seller rows and their diagnostics remain in exported audit tables.

Where the analysis stops

  • The dissatisfaction result is observational. Adjustment reduces measured confounding but does not make the 18× association causal.
  • Reviews affect only the analysis cohort. Review responders may differ from non-responders; the late-delivery model itself does not require a review.
  • Promise policy is embedded in the strongest feature. The model adds validation lift beyond the promise-only baseline, but its signal remains tied to how Olist set delivery expectations.
  • Performance and calibration move over time. Monthly backtests, prevalence shifts, and top-band overprediction require monitoring and recalibration.
  • Multi-seller attribution is unresolved. One order-level delivery timestamp cannot identify completion of multiple parcels.
  • Intervention value is policy-dependent. The economics are illustrative until effectiveness and costs are measured in the intended setting.
  • The data is historical. Straight-line distance is not route distance, and 2016–2018 marketplace operations may not represent current conditions.

The work supports retrospective analysis and a capacity-constrained risk-ranking prototype. It is neither a production-ready service nor a causal model.