Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CarHunch UK Vehicle Reliability Dataset — Volvo evaluation sample

Licence: Evaluation

Website Live sample Format Source

CarHunch — Uncover a Car's True Story

Free evaluation sample of UK MOT reliability statistics — first-time pass rates, defect patterns, severity tiers, mileage behaviour and survival curves by make, model, year and fuel — aggregated from the complete DVSA MOT history record. This sample covers Volvo only.

Nobody will pay for DVSA MOT data — it is free and open. This sample is the engineering between the raw feed and a usable cohort statistic: model normalisation, severity taxonomy, data-quality corrections, fuel-level grain, survival curves, and daily freshness.

Contains public sector information licensed under the Open Government Licence v3.0.
CarHunch is not affiliated with, or endorsed by, DVSA or DVLA.
Derived fields © Donald Simpson Limited.

Licence: evaluation only — see LICENCE.md. Full UK commercial bundle: data@carhunch.com.

Snapshot: 2026-07-19 · Filter: vehicle_count > 50 · ~2,094 cohorts · ~1.1 MB total


Who this is for

Built for teams working with UK MOT history data and used-car reliability statistics who need it aggregated rather than raw:

  • Used-car warranty and underwriting — pricing risk by cohort; structural vs routine-wear split for reserving.
  • Dealer, auction and remarketing tools — filtering stock and informing residual-value models before you bid.
  • Parts, servicing and repair platforms — predicting what a make/model/year cohort needs next.
  • Vehicle data providers and fleet analytics — adding a reliability layer to an existing feed.
  • Researchers and journalists — UK vehicle defect data at national scale, under an open-data source licence.

If you only need to look up a single car, the free consumer site does that: carhunch.com.


See it in production

This dataset is not an export made for sale — it is the layer behind a live public site. The same Volvo cohorts, rendered for humans:

  • XC60, 2018 — a single cohort row from volvo_cohort_stats.parquet, with its defect patterns and mileage distribution.
  • XC60, all years — the model rollup, which is model_norm doing its job across 4,030 raw trim strings.
  • Best year to buy an XC60 — derived analysis built on the same cohort statistics.

Figures on the site are refreshed daily; the files here are a pinned snapshot (snapshot_date is stamped on every row).


What we add over raw DVSA data

1. Model normalisation (the expensive bit)

The DVSA feed has no model taxonomy — only free-text trim strings. For Volvo alone the source holds 4,030 distinct raw model strings, which normalise to 347 models. Within this filtered sample, 611 raw strings collapse to 54.

If you have ever tried to group MOT data by model, that ratio is the whole problem. It is also the part that looks like a fortnight of work and is not.

Raw DVSA-style model (examples) model_norm
XC60 + B5 MHEV AWD AUTO XC60
XC60 + T6 RECHARGE AWD AUTO XC60
XC60 ULTRA T8 PHEV AWD AUTO XC60
XC60 + BLK ED B5 MHEV AWD AUTO XC60
XC60 ULTIMTE T8 RECHARGE AWD A XC60
XC60 + T6 PHEV AWD AUTO XC60
XC60 + B4 MHEV AWD AUTO XC60
XC60 XC60

How the join works is documented in docs/NORMALISATION.md — that document is itself part of the product.

2. Defect severity taxonomy

volvo_defect_severity.parquet is a cohort-level rollup of a hand-built severity taxonomy applied at ~1.87 billion defect rows in production. You get counts and weighted severity by tier_name (advisory, safety_wear, mechanical_safety, structural_concern, dangerous, …). Raw MOT gives you a text blob; this gives you a weighted severity model. No registration-level rows are included.

3. Corrections already applied

A naive pipeline falls into these traps; this sample already handles them:

  • Incomplete-outcome suppressionpass_rate_reliable = false where avg_tests_per_vehicle <= 1.0 (partial / unreliable outcome history).
  • Mileage anomaly separation — genuine clocking (~4.5% of vehicles) vs typos / unit errors (four false-positive classes found on real cars). Site logic; aggregates here inherit cleaned inputs.
  • Odometer unit distrustMI/KM labels are not reliable (~0.6% mislabelled); do not average across units naively.
  • Hybrid fuel classification — hybrids classified by combustion engine; treat labels like Hybrid Electric (Clean) with care.
  • Retest exclusion — retests are not counted as first-time outcomes in pass-rate metrics.

4. Fuel-level cohort grain

Stats are at make × model × manufacture_year × fuel_type — not just model/year. Most competitors stop earlier.

5. Survival curves

volvo_survival.parquet — how many vehicles from a manufacture year are still being MOT-tested in later years. Useful for warranty reserving and residual-value work.

6. Freshness

Built from CarHunch’s daily DVSA delta pipeline, not an annual dump. Every file carries snapshot_date and generated_at.


What the severity layer shows that raw MOT data cannot

Raw MOT failure text is dominated by consumables — tyres and brakes top almost every cohort, which tells you nothing. The severity taxonomy separates structural failures (corrosion, mounts, subframes — expensive, often terminal) from routine wear. That distinction is the product.

Line chart: Volvo structural defect share falls from 6.8% to 0.0% while routine wear rises from 13.5% to 62.3% across manufacture-year buckets 1987–2020

Aggregated from volvo_defect_severity.parquet (~29.7M defect records). Reproduce with the year-bucket SQL in docs/preview-tables.md.

Volvo cohorts ranked by structural share of all defects (cohorts with >20,000 defects):

model years fuel defects structural % routine-wear %
300 1990 Petrol 72,398 12.2% 11.5%
300 1987 Petrol 67,871 11.2% 10.8%
V40 1996 Diesel 30,097 10.9% 17.8%
400 1993 Petrol 479,547 10.5% 12.8%
V40 1999 Diesel 89,767 10.1% 19.1%
XC60 2017 Petrol 32,874 0.0% 60.8%
XC90 2020 Diesel 28,102 0.0% 54.9%
XC40 2020 Petrol 122,564 0.0% 68.6%

The inversion is the signal: pre-2000 cohorts spend ~11% of their defects on structural failure and little on wear; 2017+ cohorts show zero structural defects and 50–69% routine wear. For warranty reserving that is the difference between a claim that writes the car off and one that costs a tyre — and it is not recoverable from the raw feed without the taxonomy.

Reproduce it in one query — see docs/preview-tables.md, which also carries the top-20-by-dangerous-defect table.

Non-technical preview: open data/volvo_preview.csv in Excel (~20 rows).


Files

File Rows What it is
data/volvo_cohort_stats.parquet 2,094 Core cohort metrics at fuel-level grain + model_norm
data/volvo_defect_patterns.parquet 5,029 Top defect texts / type counts at model_norm × year_bucket × fuel × engine
data/volvo_defect_severity.parquet 6,284 Severity-tier rollups (cohort-level only)
data/volvo_survival.parquet 9,844 Vehicles still tested by test year
data/volvo_mileage_band_pass.parquet 2,860 Pass rate & severity score by mileage band
data/volvo_mileage_percentiles.parquet 175 Mileage p20/p40/p60/p80 by make/model
data/volvo_preview.csv 20 Excel-friendly slice

Full column dictionary: SCHEMA.md.


Quickstart

DuckDB

SELECT model, manufacture_year, fuel_type, vehicle_count,
       first_time_pass_rate, pct_with_dangerous_defect, model_norm
FROM read_parquet('data/volvo_cohort_stats.parquet')
WHERE model_norm = 'XC60' AND pass_rate_reliable
ORDER BY pct_with_dangerous_defect DESC
LIMIT 10;

Polars

import polars as pl

df = pl.read_parquet("data/volvo_cohort_stats.parquet")
print(
    df.filter(pl.col("model_norm") == "XC60")
      .sort("pct_with_dangerous_defect", descending=True)
      .select(["model", "manufacture_year", "fuel_type", "vehicle_count",
               "first_time_pass_rate", "pct_with_dangerous_defect"])
      .head(10)
)

Pandas

import pandas as pd

df = pd.read_parquet("data/volvo_cohort_stats.parquet")
print(
    df.query("model_norm == 'XC60'")
      .sort_values("pct_with_dangerous_defect", ascending=False)
      [["model", "manufacture_year", "fuel_type", "vehicle_count",
        "first_time_pass_rate", "pct_with_dangerous_defect"]]
      .head(10)
)

Join defect patterns via model_norm + year_bucket (see docs/NORMALISATION.md):

SELECT c.model, c.manufacture_year, c.fuel_type, c.vehicle_count,
       d.top_defect_texts, d.dangerous_defect_count
FROM read_parquet('data/volvo_cohort_stats.parquet') c
LEFT JOIN read_parquet('data/volvo_defect_patterns.parquet') d
  ON c.model_norm = d.model_norm
 AND c.fuel_type = d.fuel_type
 AND ((c.manufacture_year // 3) * 3 + 1) = d.year_bucket
 AND d.engine_capacity IS NULL
WHERE c.model_norm = 'V40'
LIMIT 5;

Known limitations

  • Volvo only — this is an evaluation sample, not the full UK dataset.
  • vehicle_count > 50 — small cohorts are excluded deliberately (noisy stats).
  • model vs model_normmodel is the raw DVSA-style string and may be either a normalised model (XC60) or a trim-level variant (XC60 R-DESIGN D4 AWD AUTO). model_norm is the normalised rollup key — group on it, and do not also sum the trim-level rows, or you will double-count. For a single cohort matching the public site, filter model = '<name>'.
  • Defect patterns do not share an exact key with cohort stats — join is many-to-one via model_norm + year bucket; see docs/NORMALISATION.md. Do not invent a fuzzy match.
  • CarHunch Score is not included — proprietary to carhunch.com.
  • No per-vehicle / registration / VIN data — aggregates only.
  • Not underwriting advice — validate before pricing risk.

Contact

Commercial UK licence / quarterly refresh: data@carhunch.com
Product site: carhunch.com

About

UK vehicle reliability statistics from DVSA MOT history — pass rates, defect patterns and severity tiers by make, model and year. Free Volvo evaluation sample (Parquet).

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors