Machine degradation
100 machines monitored from commissioning to failure, with an exact remaining-useful-life label on every one of 23,118 readings.
A fleet run to failure. Each machine accumulates damage toward a failure time that was declared before any row existed, so remaining useful life is exact rather than annotated afterwards. That is the thing the widely used public predictive-maintenance datasets do not have: in AI4I 2020 tool wear is as likely to fall as to rise between consecutive readings of the same machine, and there is no remaining-life label at all. Four failure modes each drive the measurement they should, sensors go missing in a structured way depending on which control pass was run, and the train and test split is by machine so nothing leaks between them.
46,336 rows across 3 tables, 526 KB zipped. Public domain (CC0), no signup, no attribution required.
What degradation looks like
readings.csv, not an illustration.These are rows from the files above. To change the fleet and watch the trajectories move, the predictive maintenance page has the declaration wired to a live chart, plus how this compares to AI4I 2020 and NASA C-MAPSS.
What is in it
unit_id, cycle, rul_cycles, machine_failure, failure_mode, tool_wear_min, vibration_mm_s, torque_nm, process_temperature_k, air_temperature_k, rotational_speed_rpm, control_type, split
the benchmark; the latent damage state is deliberately not here
unit_id, life_cycles, split, failure_mode
one row per machine
unit_id, cycle, damage
the latent state, kept out of the benchmark so it cannot leak
What holds, and how it was checked
Each line was measured against these exact files rather than asserted. The same checks ship inside the zip as INTEGRITY.txt, so you can re-run them yourself.
- rul_cycles equals life minus cycle on all 23,118 rows
- Exactly one failure row per machine, 100 of 100, each at rul_cycles 0
- tool_wear_min never decreases within a machine, because material does not come back
- Process temperature exceeds air temperature on every observed row
- The latent damage state is absent from the benchmark file
- Split is by machine: 80 train, 20 test, no machine in both
- Sensors go missing by control type, not at random: 9,347 vibration, 7,501 torque, 6,270 air
- heat_dissipation failures run 9K hotter than every other mode at failure
- Baseline: random forest 22.8 cycles MAE on held-out machines, against 58.9 for the mean
Questions it can answer
- How many cycles of life does this machine have left?
- Which failure mode is this machine heading toward?
- How early can a rising vibration signal be trusted?
- How well does a health indicator recover the true damage state?
Make your own version
The zip includes schema.yaml, which is this dataset's shape and runs as-is. Change a row count, add a column, rename a table: every foreign key still resolves, because referential integrity is a guarantee here rather than something the generator happens to get right.
pip install misata misata generate --config schema.yaml --output-dir ./dataRead the docs
Other datasets
- Retail star schema
A dimensional model you can actually practise joins on: one fact table, four dimensions, 63,170 rows, and every join resolving.
- Ecommerce storefront
A year of orders across five joined tables, with a real Q4 peak and totals that reconcile to the cent.
- B2B SaaS subscription analytics
Accounts, seats, MRR, churn and support load, where company size actually drives the plan.

