Diagnostics · Fleet Scale · Method
When the same trouble code lights up across a whole fleet and the evidence arrives in bulk — how to diagnose a population instead of a single car.
A single car gives you one observation; a fleet gives you a distribution — and a hypothesis must now explain not just that the code fired, but how common it is, who it happened to, and when it started spreading. Those stronger constraints make impostors easier to kill, but they hide a trap: the same DTC across a fleet is usually a mixture of several root causes wearing one mask. So the fleet method begins by de-mixing the population, leans on the cohort boundary to name each cause, defends hard against confounding and Simpson’s paradox, aggregates batched evidence in two careful levels, reads the prevalence curve for change-points, and ends not with a fix but with a remediation scope — who gets an over-the-air update, who gets a recall, who gets nothing.
The biggest shift is also the simplest to state: with one car you ask what broke? With a fleet you ask what explains this whole pattern?
A single faulty vehicle is one data point. A fleet throwing the same code is a distribution, and any explanation you propose has to fit three features of it at once:
Everything in the single-vehicle method still applies — grading, the impostor test, the physics referee, convergence. The fleet just adds population-level structure on top, and one new hazard we have to clear first.
Part A — One Code, Many Causes
A common trouble code is a symptom, and symptoms are shared. Treat the whole batch as one failure and you will average two real mechanisms into one that does not exist.
Here is the scenario we carry through the post. A fleet of 6,000 EVs is throwing the same code — P0AE0, “reduced charge rate.” The batch of evidence: build records (plant, build week, firmware, charge-connector supplier lot), telemetry summaries, warranty claims, and service notes.
It is tempting to ask “what causes P0AE0?” as if there is one answer. But a charge-rate code can be tripped by many mechanisms, and across 6,000 cars more than one of them is probably active. In our fleet there are in fact two:
Signature: reduced charge rate correlated with low temperature. Onset tracks the v5.1 software rollout.
Signature: reduced charge rate correlated with connector temperature and current. Onset tracks those build weeks entering service.
Both set the identical code. If you pool all 6,000 cars and fit one explanation, you get a blurry average that fits neither — a “cold-ish, connector-ish, sort-of” cause that no fix actually addresses. That is the mixture trap.
The fix for a mixture is to split it into homogeneous groups before reasoning about cause. You do that by giving each car a short fingerprint and grouping cars whose fingerprints match.
For each vehicle, summarize the code event into a small signature: when did the throttling happen (cold? hot? high current?), how severe, how often, under what conditions. Cars driven by the same mechanism will have similar signatures and cluster together; the clusters are your candidate sub-populations. Then you run the ordinary single-vehicle method inside each cluster, where there really is one cause.
input fleet of cars with the same code · batch evidence
output sub-populations, each with (likely) one cause
for car in affected(fleet):
sig[car] ← signature(car) # conditions, severity, timing of the event
clusters ← cluster(sig) # group similar fingerprints (mixture model / k-means)
for C in clusters:
check C is homogeneous # one tight signature, not a smear
single_vehicle_rca(C) # now there is one cause to find
return clusters with their causes
A genuine sub-population has a tight, separable signature and a sensible size — not a fuzzy blob you split by eye. If the clusters overlap heavily, you may have one cause with a spread of severities, not two causes. Treat clustering as a hypothesis to be confirmed by the cohort boundary in §04, not as the answer.
Part B — The Cohort Contrast
On one car, comparing affected to unaffected was a luxury. Across a fleet it is the main engine — the line between who fails and who doesn’t usually points straight at the mechanism.
Within a cluster, line the affected cars up against the healthy ones and ask: what attribute best separates them? Build plant, firmware version, build week, supplier lot, climate. The attribute that cleanly divides failed from healthy is your prime suspect.
For Cluster 1, the dividing line is sharp: every affected car runs firmware ≥ v5.1, across all plants, and healthy cars run older firmware. For Cluster 2, the line is Supplier-B connectors from build weeks 12–18, at one plant. Two clusters, two clean boundaries, two causes — exactly what de-mixing was for.
Notice what the boundary gives you for free that one car never could: the exact affected-population definition — a rule over VINs (“firmware ≥ v5.1” or “Supplier-B connector, weeks 12–18”). That rule is what a remediation campaign in §09 will be written against.
The impostor from the single-car method comes back at fleet scale — bigger and better disguised. A correlation across the whole fleet can point the wrong way, and even reverse once you look inside the subgroups.
Suppose you tally the raw code rate by plant and find Plant A at 6%, Plant B at 4%. Plant A looks like the problem. But split each plant by firmware and the story flips:
| Group | Plant A | Plant B | Who’s worse? |
|---|---|---|---|
| Older firmware | 2% | 3% | B |
| Firmware ≥ v5.1 | 9% | 10% | B |
| Aggregate (all cars) | 6% | 4% | A?! |
Never act on a raw fleet-wide rate. Condition on the structural confounders first — plant, firmware, build week, supplier, climate, usage — and only trust a difference that holds inside the strata. The cohort boundary of §04 and this stratification are the same discipline doing double duty.
Part C — Aggregating Batched Evidence
A batch of millions of rows feels authoritative. But carelessly piled together it produces false certainty just as easily as insight. The cure is to aggregate in two disciplined levels.
The single biggest aggregation mistake is to throw every row from every car into one pile and let the counts speak. A car that logged 50,000 rows would then shout fifty thousand times louder than one that logged ten — for no good reason.
Do it in two levels. Level one: reduce each car’s raw evidence to a single tidy summary — its signature, its build attributes, and its outcome (did the code fire, how badly). One car, one row. Level two: reason across those rows — stratify, fit a model, compare cohorts. This keeps every vehicle to one vote and stops a few data-heavy cars from hijacking the conclusion. It is the independence rule from the prequel, enforced by structure.
Fleet data is never a clean random sample. It is filtered by who reports, who comes in for service, and who is still alive to log — and each filter bends the picture.
Three biases to name out loud, because they quietly distort prevalence and stratification:
Part D — Time & the Decision
A fleet has a clock. The shape of the failure over time often pins the cause to a specific event — and the end product is not a fix but a campaign.
Plot how many new cases appear each week and the picture often tells you the cause before any deep analysis. A sudden change in slope — a change-point — usually lines up with something real: a software rollout, a supplier switch, a season.
In our fleet the curve has two separate take-offs, and that alone confirms the mixture. One rise begins exactly when firmware v5.1 starts rolling out over the air; a second, later rise begins as the Supplier-B build-week-12–18 cars reach the field. Two change-points, two causes, each tied to its own event.
On one car you end with a repair. On a fleet you end with a decision about thousands of cars: who needs fixing, by what means, and how urgently. The de-mixing pays off here most of all — because the two causes need completely different campaigns.
The affected-population rules from §04 become the campaign’s targeting. The onset and forecast from §08 set the urgency. And the nature of each cause sets the method:
Scope each campaign by weighing the forecasted failures it prevents (§08) against its cost and the risk of the remedy itself — exactly the cost-aware logic from the sufficiency post, now spending recall dollars instead of measurements. A narrow, well-targeted recall beats a fleet-wide panic on every axis that matters.
The fleet method is the single-car method wrapped in two new moves: de-mix at the front, decide a campaign at the back — and stratify relentlessly in between.
input cluster cars with build attributes A · outcome (affected?)
output the rule over attributes that best separates failed from healthy
for attr in A: # plant, firmware, build-week, supplier lot, climate
score[attr] ← separation(split cars by attr) # e.g. information gain
best ← argmax score
if leaf(best) is near-pure: return rule = best # the affected-population definition
else: recurse on the impure child # a second attribute may be needed
clusters ← de_mix(fleet, code) # §03 — split the mixture
for C in clusters:
rule ← cohort_boundary(C) # §04 — who fails
if not holds_within_strata(rule): continue # §05 — drop confounded impostor
confirm_mechanism(C) # referee — single-car method
onset, forecast ← time_analysis(C) # §08 — change-point + projection
plan[C] ← remediation_scope(rule, forecast) # §09 — OTA / recall / targeted
return plan per cluster
Putting it together on the running example, in one pass.
De-mix (§03). All 6,000 cars share P0AE0. Reducing each affected car to a signature and clustering reveals two tight groups: ~340 cars that throttle in the cold, and ~120 that throttle when the connector runs hot. One code, two sub-populations.
Cohort boundary (§04). Cluster 1’s affected cars are exactly those on firmware ≥ v5.1, every plant. Cluster 2’s are exactly the Supplier-B connectors from build weeks 12–18. Two clean rules over VINs.
Confounding check (§05). The raw rate made Plant A look worst — but stratifying by firmware reversed it: Plant A only shipped more v5.1 cars. The “plant” signal was an impostor; firmware is the real axis. Dropped.
Confirm (referee). Inside each cluster, the single-car method closes it out: Cluster 1’s charging logic throttles below a temperature threshold in v5.1 (trace the code); Cluster 2’s connectors show high resistance and heating under load (measure the joint). Two confirmed mechanisms.
Onset & forecast (§08). The curve take-offs line up with the v5.1 rollout and the lot entering service — independent confirmation of two causes — and project a few hundred more cases if nothing is done.
OTA software campaign: push v5.2 to all ≥v5.1 cars. Remote, days, low cost, no service visit. Kill-switch: post-patch cold-charge rates return to normal.
Targeted recall: replace the connector on ~120 specific VINs only. Service visit, higher cost, but bounded. Kill-switch: replaced joints stop heating and throttling.
One trouble code; two causes; two proportionate fixes touching 460 cars instead of 6,000. That gap — between a blind fleet-wide recall and a precise, de-mixed response — is the entire value of doing fleet RCA properly.
Cluster the affected cars by signature before asking “what causes this code.” Pooling distinct mechanisms produces an average cause that no fix addresses.
The build attribute that cleanly separates failed from healthy — firmware, lot, plant, climate — is your prime suspect and your affected-population rule in one.
A fleet-wide correlation can reverse inside subgroups. Trust a difference only if it survives conditioning on plant, firmware, build week, supplier, and climate.
Reduce each car to a single row first, so a chatty logger can’t outvote the fleet. Volume is not confidence.
Warranty batches over-represent severe, reporting cars and can miss the cars that failed hardest and went silent. Absence of signal is not absence of fault.
Plot new cases over time. A take-off aligned to an OTA, a supplier switch, or a season is strong, cheap evidence — and two take-offs mean two causes.
The fleet output is a decision about thousands of cars: who, by what means, how urgently — not a single repair.
De-mixing is what lets you OTA the firmware group and recall only the bad-lot VINs — instead of a fleet-wide overreaction or an under-reaction that misses a real hazard.
Fleet RCA borrows from epidemiology, reliability engineering, and statistics as much as from diagnosis. Entry points, grouped.
K. J. Rothman, S. Greenland & T. L. Lash, Modern Epidemiology (3rd ed., 2008). Case-control reasoning, confounding, and stratified analysis — the discipline of comparing affected to unaffected populations.
N. Mantel & W. Haenszel, “Statistical Aspects of the Analysis of Data From Retrospective Studies of Disease” (1959). The classic stratified estimate that combines subgroup evidence without the Simpson reversal.
E. H. Simpson, “The Interpretation of Interaction in Contingency Tables” (1951). The paradox of §05, at its source.
J. Pearl, Causality: Models, Reasoning, and Inference (2nd ed., 2009). When a stratified or adjusted comparison does and does not recover a causal effect.
G. McLachlan & D. Peel, Finite Mixture Models (2000). The formal account of data generated by several hidden sub-populations — the de-mixing of §03.
T. Hastie, R. Tibshirani & J. Friedman, The Elements of Statistical Learning (2nd ed., 2009). Clustering, mixture models, and the decision trees behind the stratification of §04.
W. Q. Meeker & L. A. Escobar, Statistical Methods for Reliability Data (1998). Field-failure and warranty analysis, hazard and life distributions — the forecasting of §08–§09.
W. Nelson, Applied Life Data Analysis (1982). Practical life-data and failure-rate estimation for fielded populations.
J. F. Lawless, Statistical Models and Methods for Lifetime Data (2nd ed., 2003). Recurrent events and lifetime modeling underlying fleet prognosis.
A. Gelman & J. Hill, Data Analysis Using Regression and Multilevel/Hierarchical Models (2007). The two-level aggregation of §06 done properly — vehicle within fleet.
M. Basseville & I. Nikiforov, Detection of Abrupt Changes (1993). The change-point detection behind reading the onset curve in §08.
J. de Kleer & B. C. Williams, “Diagnosing Multiple Faults” (1987); R. Reiter, “A Theory of Diagnosis from First Principles” (1987). The multiple-cause reasoning that, at population scale, becomes the mixture problem.
These are orientation points into large literatures, cited to show the lineage of the method rather than as the source of any single claim here. Titles and years are given so you can find them.