Compute Residual-Based Metrics for Posterior Predictions
Source:R/compute_residual_metrics.R
compute_residual_metrics.RdComputes residuals between observed antibody measurements and posterior predicted values at observed timepoints. Returns pointwise residuals and/or summary metrics (MAE, RMSE, SSE) at multiple aggregation levels.
This function provides quantitative posterior predictive diagnostics to
complement visual assessments from plot_predicted_curve(). It evaluates
how well the model predictions match observed data at the individual level.
Arguments
- model
An
sr_modelobject (returned byrun_mod()) containing samples from the posterior distribution of the model parameters.- dataset
A dplyr::tbl_df with observed antibody response data. Must contain:
id: participant IDtimeindays(or the time variable specified in the dataset attributes)value(or the value variable specified in the dataset attributes)antigen_iso: antigen-isotype combination
- ids
Character vector of participant IDs to compute residuals for.
- antigen_iso
The antigen isotype (e.g., "HlyE_IgA" or "HlyE_IgG").
- scale
Character string specifying the scale for residual computation. Options:
"original": Compute residuals on the original measurement scale (default)."log": Compute residuals on the log scale, i.e.,log(obs) - log(pred_med). Non-positive values are removed with a warning.
- summary_level
Character string specifying the aggregation level for summary metrics. Options:
"pointwise": Return one row per observation with individual residuals (no summary)."id_antigen": Summary metrics perid × antigen_isocombination (default)."antigen": Summary metrics perantigen_iso(aggregated across IDs)."overall": Single overall summary across all IDs and antigens.
Value
A dplyr::tbl_df containing:
If summary_level = "pointwise":
id: participant IDantigen_iso: antigen-isotype combinationt: time in daysobs: observed valuepred_med: posterior median predictionpred_lower: 2.5% quantile of posterior predictionspred_upper: 97.5% quantile of posterior predictionsresidual: raw residual (obs - pred_med)abs_residual: absolute residual (abs(obs - pred_med))sq_residual: squared residual ((obs - pred_med)^2)
If summary_level is "id_antigen", "antigen", or "overall":
id: participant ID (if applicable to summary level)antigen_iso: antigen-isotype combination (if applicable)MAE: mean absolute errorRMSE: root mean squared errorSSE: sum of squared errorsn_obs: number of observations used in calculation
Examples
sees_model <- serodynamics::nepal_sees_jags_output
sees_data <- serodynamics::nepal_sees
# Example 1: Pointwise residuals for a single ID
pointwise_resid <- compute_residual_metrics(
model = sees_model,
dataset = sees_data,
ids = "sees_npl_128",
antigen_iso = "HlyE_IgA",
scale = "original",
summary_level = "pointwise"
)
print(pointwise_resid)
#> # A tibble: 5 × 10
#> id antigen_iso t obs pred_med pred_lower pred_upper residual
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 sees_npl_128 HlyE_IgA 29 243. 340. 115. 1775. -96.9
#> 2 sees_npl_128 HlyE_IgA 83 222. 245. 103. 1026. -22.7
#> 3 sees_npl_128 HlyE_IgA 161 129. 171. 80.9 509. -42.2
#> 4 sees_npl_128 HlyE_IgA 459 19.8 61.9 22.1 120. -42.1
#> 5 sees_npl_128 HlyE_IgA 552 25.1 49.0 13.7 94.8 -23.9
#> # ℹ 2 more variables: abs_residual <dbl>, sq_residual <dbl>
# Example 2: Summary metrics per ID × antigen_iso (default)
summary_per_id <- compute_residual_metrics(
model = sees_model,
dataset = sees_data,
ids = "sees_npl_128",
antigen_iso = "HlyE_IgA",
scale = "original"
)
print(summary_per_id)
#> # A tibble: 1 × 6
#> id antigen_iso MAE RMSE SSE n_obs
#> <chr> <chr> <dbl> <dbl> <dbl> <int>
#> 1 sees_npl_128 HlyE_IgA 45.6 53.0 14028. 5
# Example 3: Multiple IDs with summary per ID
multi_id_summary <- compute_residual_metrics(
model = sees_model,
dataset = sees_data,
ids = c("sees_npl_128", "sees_npl_131"),
antigen_iso = "HlyE_IgA",
scale = "original",
summary_level = "id_antigen"
)
print(multi_id_summary)
#> # A tibble: 2 × 6
#> id antigen_iso MAE RMSE SSE n_obs
#> <chr> <chr> <dbl> <dbl> <dbl> <int>
#> 1 sees_npl_128 HlyE_IgA 45.6 53.0 14028. 5
#> 2 sees_npl_131 HlyE_IgA 73.5 99.3 49280. 5
# Example 4: Overall summary across multiple IDs
overall_summary <- compute_residual_metrics(
model = sees_model,
dataset = sees_data,
ids = c("sees_npl_128", "sees_npl_131"),
antigen_iso = "HlyE_IgA",
scale = "original",
summary_level = "overall"
)
print(overall_summary)
#> # A tibble: 1 × 4
#> MAE RMSE SSE n_obs
#> <dbl> <dbl> <dbl> <int>
#> 1 59.5 79.6 63308. 10
# Example 5: Log-scale residuals
log_resid <- compute_residual_metrics(
model = sees_model,
dataset = sees_data,
ids = "sees_npl_128",
antigen_iso = "HlyE_IgA",
scale = "log",
summary_level = "id_antigen"
)
print(log_resid)
#> # A tibble: 1 × 6
#> id antigen_iso MAE RMSE SSE n_obs
#> <chr> <chr> <dbl> <dbl> <dbl> <int>
#> 1 sees_npl_128 HlyE_IgA 0.505 0.624 1.95 5