Handling Missing Values in C++
Real datasets have holes: a sensor dropped out, a form field was left blank. A model that expects a full numeric matrix cannot consume a gap, so the gaps must be filled first. The simplest reliable strategy is imputation: replace each missing entry with a summary of the column it lives in, computed from the training data.
Marking the Gaps
First we need a value that means "missing." A floating-point NaN is ideal: it survives in a double column and is easy to test for with isnan, so a missing entry never gets mistaken for a real $0$.
#include <bits/stdc++.h>
using namespace std;
static const double NA = nan(""); // the "missing" marker
Mean and Median, Skipping NaNs
Both statistics are computed over the present values only. The mean is the obvious fill, but it is pulled toward extreme values; the median is robust to outliers, which often makes it the safer default.
double columnMean(const vector<double>& col) {
double sum = 0; int n = 0;
for (double v : col) if (!isnan(v)) { sum += v; n++; }
return sum / n;
}
double columnMedian(vector<double> col) {
vector<double> present;
for (double v : col) if (!isnan(v)) present.push_back(v);
sort(present.begin(), present.end());
int n = present.size();
return n % 2 ? present[n/2] : (present[n/2 - 1] + present[n/2]) / 2;
}
vector<double> impute(const vector<double>& col, double fill) {
vector<double> out = col;
for (double& v : out) if (isnan(v)) v = fill;
return out;
}
Running It
Take a column with two gaps and one outlier ($100$), and fill it both ways:
int main() {
vector<double> col = {1, 2, NA, 4, 100, NA};
double mean = columnMean(col);
double median = columnMedian(col);
printf("train mean (skip NA) = %.2f median = %.2f\n", mean, median);
// print impute(col, mean) and impute(col, median)
}
The lone $100$ drags the mean up to $26.75$, so mean-imputation fills the gaps with a value larger than every non-outlier in the column, a poor guess. The median, $3$, ignores the outlier and fills with a typical value. That robustness is why median imputation is a sensible default whenever a column may contain extreme values.
mean (or median) and reusing it to fill the test column keeps the test set untouched by its own statistics, the same rule the scaler follows. With the holes filled, the matrix is ready for the decision tree and the rest of the models.