Missing values are absent entries in an otherwise structured dataset. What matters is not how many there are but why they are absent. If a temperature sensor drops readings uniformly at random, filling the gap is a reasonable approximation. If it drops readings specifically when the plant room exceeds its rated temperature, the absence is correlated with the outcome you are modelling, and any imputation that ignores that erases the most informative pattern in the data.
Treat missingness as a variable in its own right before treating it as a defect. In sensor estates the pattern of failure is frequently more predictive than the readings that survived.
What problem does this solve?
A facilities team runs analytics over a mixed-use tower: zone temperature, relative humidity, CO2, occupancy counts and sub-metered power at fifteen-minute intervals across 340 points. Around 9% of expected readings are absent over a twelve-month window.
The gaps have several distinct causes. Some wireless sensors on the upper floors miss readings during high wind because of antenna movement. Several CO2 sensors drop out during their scheduled auto-calibration. Two chiller power meters lose long blocks during network switch maintenance. And a handful of zone temperature sensors stop reporting precisely when the plant room runs hottest, because the transmitter exceeds its own operating range.
The team's first pass filled every gap with the column mean. Energy consumption forecasting accuracy improved slightly on paper. In production the model failed to anticipate exactly the peak-load afternoons it was built for — because the readings that mattered most were the ones that had been absent, and they had all been replaced with an average summer afternoon.
How the solution works
Classify the mechanism before choosing a method. MCAR means the probability of absence is unrelated to anything — a random packet loss. MAR means absence is explained by other observed variables — dropouts correlate with recorded wind speed. MNAR means absence depends on the unobserved value itself — the sensor fails because the temperature is high.
For MCAR, most reasonable imputations are defensible. For MAR, use methods that condition on the other columns, such as iterative or KNN imputation. For MNAR, no imputation is correct on its own; the fact of absence must be carried as a feature.
For time series, respect the axis. Temperature at 14:00 is far better estimated from 13:45 and 14:15 than from the annual mean, so short gaps take interpolation and long gaps are better left absent than invented.
Add missingness indicators. A binary column marking that a value was absent lets the model learn the pattern directly, which is the only honest way to handle MNAR without pretending to know the missing number.
- 1Quantify per point Compute missingness rates per sensor, per hour of day and per month rather than one dataset-level percentage.
- 2Test for MCAR Compare the distribution of other variables between rows where the target column is present and rows where it is absent. A material difference rules out MCAR.
- 3Look for MAR structure Model the missingness indicator itself as a classification target. If other columns predict absence well, the mechanism is MAR and conditional imputation is appropriate.
- 4Suspect MNAR at the range limits Check whether the last recorded values before a gap cluster near a sensor's operating limit. That is the signature of a device failing under the condition being measured.
- 5Impute inside the fold Fit the imputer on training data only. Fitting on the whole dataset lets test-set statistics flow backwards into training.
Reference architecture
Missing data touches four layers, and only one of them is the imputation call.
| Layer | What it contains |
|---|---|
| Acquisition layer | Device health, radio conditions, calibration schedules and network maintenance windows — the physical causes of absence. |
| Classification layer | Determination of MCAR, MAR or MNAR per sensor, since the mechanism decides which methods are valid. |
| Imputation layer | Method chosen to match the mechanism and fitted inside the training fold only. |
| Monitoring layer | Missingness rates tracked over time, because a rising rate is a maintenance signal before it is a data-quality one. |
Deployment options: Occupancy counts and zone-level data can become personal data when they identify individual working patterns, particularly in small tenancies, so retention and aggregation levels should be agreed before the analytics platform is built.
Key capabilities
Per-sensor missingness profiling
Rates broken down by point, hour and season instead of one dataset-level percentage that hides everything.
availableMechanism classification
An MCAR, MAR or MNAR determination per sensor, which is what makes a method choice defensible.
availableLeak-safe imputation pipeline
Imputers fitted inside time-ordered folds so reported error reflects deployment.
custom developmentMissingness drift monitoring
Alerting when a sensor's dropout rate changes, catching device degradation before it reaches the model.
custom developmentIntegrations
In a building estate, missing data is a maintenance fact before it is a modelling problem, so the integration surface includes the BMS and the CMMS as well as the analytics platform.
| System | Integration point & data exchanged | Direction |
|---|---|---|
| Building management system | Point health and communication status read alongside values, so a gap can be attributed rather than guessed at. → Facility Management | bi-directional |
| Maintenance management | Sustained dropout raised as a work order, since the durable fix is usually a device rather than an imputer. | bi-directional |
| Analytics pipeline | Imputation and indicator generation versioned with the model so a retrain reproduces the same treatment. → Data Leakage: The Model That Only Works Before Deployment | bi-directional |
Industry use cases
Energy optimisation
Load forecasting where the gaps cluster on peak days is the case most damaged by naive filling.
HVAC predictive maintenance
Dropout patterns often precede device failure and are a feature rather than a nuisance.
Indoor air quality reporting
Calibration windows create regular, explainable gaps that should be excluded rather than imputed.
Tenant billing and sub-metering
Estimated consumption must be auditable, which usually rules out opaque imputation entirely.
UAE & GCC considerations
Gulf summer conditions create a specific and common MNAR pattern: wireless transmitters and battery-powered sensors in plant rooms, roof spaces and unconditioned risers exceed their rated operating temperature and stop reporting exactly during the peak-load hours the analytics exist to predict. Sensor dropout in these locations should be treated as a seasonal signal rather than a random fault, and the operating temperature range of each device should be checked against the actual conditions of its installed location before any gap-filling strategy is chosen. Where consumption figures feed tenant billing, estimated values normally have to be identifiable and auditable, which constrains the methods available.
Implementation approach
- 1Profile before filling Produce missingness rates per point, per hour and per month. A single overall percentage conceals every pattern that matters.
- 2Classify the mechanism Test whether other columns predict absence, and inspect the values immediately preceding gaps for range-limit clustering.
- 3Match the method Time interpolation for short gaps, conditional imputation for MAR, and indicators wherever MNAR is suspected.
- 4Cap the gap length Set a maximum interpolation span. Beyond it, leave the value absent rather than manufacturing a plausible line.
- 5Monitor the rate Track dropout per sensor after deployment and route sustained increases to maintenance.
Security & deployment
Occupancy counts and zone-level environmental data can identify individual working patterns in small tenancies, and imputation can make that worse by producing a continuous inferred record where the real data was sparse. Agree aggregation levels and retention with the building owner before modelling, and keep imputed values flagged so an inferred occupancy figure is never mistaken for a measurement in a tenant-facing report.
A worked example
One zone temperature sensor over a single July week at fifteen-minute resolution, with a 90-minute gap on the hottest afternoon.
- The surrounding readings. The last value before the gap is 38.4 C at 14:15; the first after is 37.9 C at 15:45. The annual column mean is 24.1 C.
- Global mean imputation. Six consecutive intervals are filled with 24.1 C, inserting a 14-degree trough into the hottest afternoon of the year.
- What the model learns. Peak cooling load appears to coincide with a sharp temperature drop, which is the opposite of the physical relationship.
- Linear interpolation. The gap fills smoothly from 38.4 to 37.9, preserving the shape but assuming nothing unusual happened in between.
- Interpolation plus indicator. The same interpolated values, with a flag marking the interval as imputed and the reason as transmitter over-range.
The last row is the honest treatment. Interpolation keeps the temporal shape plausible, and the indicator lets the model learn that this sensor stops reporting under extreme heat — which is a genuine predictor of peak load, and precisely the pattern global mean imputation destroyed.
In code
Three things worth doing in order: test whether missingness is random, compare methods honestly inside folds, and keep the indicator.
import numpy as np
import pandas as pd
from sklearn.experimental import enable_iterative_imputer # noqa: F401
from sklearn.impute import SimpleImputer, KNNImputer, IterativeImputer, MissingIndicator
from sklearn.ensemble import HistGradientBoostingRegressor, RandomForestClassifier
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import TimeSeriesSplit, cross_val_score
# 1. Is the missingness random? Predict the gap itself.
# High AUC here means other columns explain absence -> MAR, not MCAR.
is_missing = df["zone_temp"].isna().astype(int)
predictors = df.drop(columns=["zone_temp"]).fillna(-999)
auc = cross_val_score(
RandomForestClassifier(n_estimators=200, random_state=0),
predictors, is_missing, cv=TimeSeriesSplit(n_splits=4), scoring="roc_auc",
).mean()
print("missingness predictability (AUC):", round(auc, 3))
# 2. Where do gaps start? Values near the sensor limit suggest MNAR.
gap_start = df["zone_temp"].notna() & df["zone_temp"].shift(-1).isna()
print("last value before gap - describe:")
print(df.loc[gap_start, "zone_temp"].describe())
# 3. Compare strategies inside time-ordered folds.
# The indicator is kept alongside the imputed values, never instead of them.
with_flag = FeatureUnion([
("imputed", IterativeImputer(max_iter=10, random_state=0)),
("was_missing", MissingIndicator(features="all")),
])
strategies = {
"mean": SimpleImputer(strategy="mean"),
"knn": KNNImputer(n_neighbors=5),
"iterative": IterativeImputer(max_iter=10, random_state=0),
"iterative+indicator": with_flag,
}
cv = TimeSeriesSplit(n_splits=5)
for name, imputer in strategies.items():
pipe = Pipeline([("impute", imputer),
("model", HistGradientBoostingRegressor(random_state=0))])
s = cross_val_score(pipe, X, y_energy, cv=cv, scoring="neg_mean_absolute_error")
print(f"{name:20s} MAE {-s.mean():.3f} +/- {s.std():.3f}")
# Short gaps only: interpolation is a time-series operation, not a column statistic.
df["zone_temp_interp"] = df["zone_temp"].interpolate(method="time", limit=4)An AUC for predicting absence, a summary of the values immediately preceding gaps, and mean absolute error per strategy. A high AUC rules out MCAR. Values clustered near the top of the sensor range before gaps indicate MNAR, and in that case the indicator column usually improves the model more than any change of imputer.
Diagnostic checks
- Compute missingness per sensor, per hour of day and per month; a dataset-level percentage hides seasonal and diurnal structure.
- Train a classifier to predict the missingness indicator. High AUC means the mechanism is not MCAR.
- Inspect the last recorded value before each gap. Clustering near a device's operating limit is the MNAR signature.
- Compare mean imputation against interpolation on the same time-ordered folds; a large difference means the temporal axis carries real signal.
- Check whether gaps align with calibration schedules or network maintenance windows, which are explainable and should be excluded rather than filled.
- Verify the imputer is fitted inside the fold; a global fit leaks test statistics into training.
When to use it
- Gaps are short relative to the sampling interval and the underlying quantity varies smoothly.
- The mechanism has been classified and a method chosen to match it.
- The model requires complete rows and dropping them would discard a material share of the data.
- Missingness indicators can be carried alongside the imputed values.
When not to use it
- A sensor is absent for days or weeks, where interpolation manufactures a plausible line with no supporting evidence.
- Absence is MNAR and the model consumes only the imputed value without the indicator, which erases the informative pattern.
- Values feed billing or regulatory reporting where estimates must be separately identifiable and auditable.
- The missingness rate for a point is so high that the remaining readings cannot support any estimate worth trusting.
Limitations & prerequisites
- No imputation adds information; it produces a plausible value, not a correct one.
- MNAR cannot be corrected from the observed data alone, which is why the indicator matters more than the method.
- Iterative imputation is expensive on wide sensor estates and its uncertainty is not reflected in a single filled value.
- Interpolation assumes smooth behaviour between endpoints, which is exactly what a fault event violates.
Methods against gap type
Selection follows the mechanism and the gap length, not convenience.
| Method | Appropriate when | Failure mode |
|---|---|---|
| Drop rows | Few gaps, MCAR | Discards peak-day rows if MNAR |
| Global mean | Quick baseline only | Flattens temporal and seasonal shape |
| Time interpolation | Short gaps in smooth signals | Invents a line across long outages |
| KNN imputation | MAR with correlated points | Costly and sensitive to scaling |
| Iterative imputation | MAR with multivariate structure | Expensive; single value hides uncertainty |
| Missingness indicator | MNAR, or any mechanism | None on its own; pair it with a value |
For building sensor data the practical default is time interpolation with a capped span, always paired with an indicator column.
Key takeaways
- Why a value is missing matters more than how many are missing.
- MCAR, MAR and MNAR require different treatments and only the first is forgiving.
- Global mean imputation destroys temporal and seasonal structure in sensor data.
- A missingness indicator preserves MNAR information that no imputer can recover.
- Fit imputers inside time-ordered folds, and monitor dropout rates as a maintenance signal.
FAQ
MCAR means absence is unrelated to anything. MAR means absence is explained by other observed columns. MNAR means absence depends on the missing value itself — a sensor failing because the temperature is too high.
It replaces the gap with an annual average, which in a seasonal signal inserts a value that is wrong by a wide margin and destroys the temporal shape the model needs.
Train a classifier to predict the missingness indicator from the other columns. If it predicts well, absence is structured and MCAR is ruled out.
It is close to free and it is the only mechanism-agnostic way to preserve MNAR information. The main reason not to is a strict feature budget.
Set the limit from the physical process rather than a rule of thumb. Zone temperature moves slowly enough for an hour; occupancy counts can change completely in fifteen minutes.
Yes, when the mechanism is MCAR and the loss is small. It becomes dangerous under MNAR, because the dropped rows are exactly the extreme conditions of interest.
Inside the training fold. Fitting an imputer on the whole dataset lets test-set statistics inform training and inflates the reported score.
Several implementations handle missing values natively by learning a default split direction, which is often better than filling. Confirm the behaviour of the specific library rather than assuming it.
Sensor history full of gaps you cannot explain?
Send the point list, the polling interval and a month of raw history. We will classify the missingness mechanism per sensor and tell you which gaps can be filled and which are telling you something.
Schedule a building data quality reviewSources & evidence
- scikit-learn: imputation of missing values — Official reference for SimpleImputer, KNNImputer, IterativeImputer and MissingIndicator.
- Rubin, Inference and Missing Data (Biometrika 1976) — Origin of the MCAR, MAR and MNAR classification.
- pandas: interpolate — Reference for time-aware interpolation and gap limits.
- scikit-learn: HistGradientBoostingRegressor — Reference for native handling of missing values during tree splits.
Vendor and product names are trademarks of their respective owners; references are for technical context and do not imply partnership, certification or endorsement unless stated on the vendor's official pages.