Preprocessing

Preprocessing is the step where raw mobility data is prepared before imputation or analysis.

Raw counter data is often imperfect. Counters may stop working, report suspicious zero values, or contain abnormal observations.

The goal of preprocessing is to make the dataset more reliable before missing values are filled.

Imputation works better when the input data has already been checked.

For example, a missing value and a true zero are not always the same thing.

In mobility data:

  • A true zero may mean no traffic was observed

  • A suspicious zero may mean the counter was not working

Preprocessing helps separate these cases before imputation.

What preprocessing does

Preprocessing works in two stages.

1. Measurement-error removal (always applied). Using fixed, configurable rules, preprocess detects and nulls out observations that look like sensor errors rather than real counts, such as whole zero-days, sustained low-count runs, or short “islands” of real-looking data surrounded by long suspicious gaps. The exact rules differ between hourly and daily data (for example, night hours are treated differently for hourly data). These rules are controlled by PreprocessConfig (see Configuration).

2. Outlier scoring and thresholding (tunable per run). Each remaining observation gets an outlier score, based on residuals from an STL (Seasonal-Trend decomposition using LOESS) decomposition of the counter’s time series. Observations scoring above a threshold are treated as outliers and replaced with NaN. The default threshold (20 for daily data, 45 for hourly data) was tuned on a specific dataset and may not suit yours as-is.

Output

preprocess.run() returns the input data with:

  • suspicious/unlikely observations replaced with NaN

  • an out_score column, giving the outlier score computed for each observation

Call pp.report() afterward for a summary of what was changed during the run. See Pipeline notes for details on reading it.

Usage

For the basic call, see Quickstart. Once you have a preprocessed result, you can inspect and re-tune it:

pp.plot_outliers(counters=None, max_counters=5)

# adjust and re-run with a custom threshold after inspecting the outliers through the plot function, if the default does not fit
df_preprocessed = pp.run(
    df_raw=df,
    counter_col=counter_col,
    timestamp_col=timestamp_col,
    count_col=count_col,
    threshold=15,
)