--- title: "07 — Correction reports and quality assessment" author: "Pierpaolo Massoli" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{07 — Correction reports and quality assessment} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = FALSE) ``` > Operational examples assume that the SSPICE project root is the working directory. Operational chunks are not executed when building the vignette because they require the project data. Standalone chunks explicitly marked `eval=TRUE` are exceptions. # Why assess the result? Algorithm termination does not imply that all records are correct. Step 11 compares original and corrected data, uses the final extended-DAG routing check stored in the correction result, and produces a quality report. It also uses the initial check, exact donor records, elapsed time and donor provenance when available. ```{r report-step} source(file.path("scripts", "11_correction_quality_report.R")) ``` The script reads `correction_result.rds` and `corrected_questionnaire_data.rds` from Step 10, together with `prepared_data_with_logical_edits.rds` and `questionnaire_extended_DAG.rds` from Step 09. It produces `correction_quality_report.rds`, an HTML report and CSV tables in `correction_quality_output_dir`, or in the `quality-report` subdirectory of the correction output directory. # Reading the report | Question | Evidence to inspect | |:--|:--| | How many records are resolved? | Record summary, separating resolved and unresolved cases | | Do any violations remain? | Initial and final reports by record and variable | | Which values changed? | Change tables and breakdown by change type | | Were donors admissible? | Provenance and diagnostics of the EXACT pool | | Were constrained variables respected? | Audit of immutable variables and exogenous auxiliary variables | | What is the computational cost? | Elapsed time and execution summary | Assess the resolution rate separately from persistent errors. A record may remain unresolved; do not classify it as corrected merely because a value changed. Retain complete outputs and pilot settings to reproduce comparisons. # Selecting the result to assess Step 11 must not inadvertently use the default pilot directory after a run was saved elsewhere. Use the same output directory as Step 10 and the same original extended data. Run this example from the project root: ```{r quality-config, eval=FALSE} pkgload::load_all(".", export_all = FALSE, helpers = FALSE) run <- new.env(parent = globalenv()) sys.source("scripts/00_config.R", envir = run) run$config$correction_output_dir <- "output/corrected-full-STRATUM" run$config$correction_quality_output_dir <- file.path( run$config$correction_output_dir, "quality-report" ) run$correction_quality_report <- SSPICE::correction_quality_report run$`%||%` <- function(x, y) if (is.null(x)) y else x sys.source("scripts/11_correction_quality_report.R", envir = run) ``` The function uses `final_check` when supplied, otherwise `correction_result$final_routing_check`. It does not automatically run a new, independent validation of the final dataset. The script may, however, recompute the initial check if neither a configured nor a saved check is found. # Interpreting the counts `records_resolved` measures constraint resolution, not the statistical accuracy of imputation relative to unknown true values. `records_changed` includes modified records even if they remain unresolved. `fills`, `blanks` and `mode_changes` distinguish missing-to-value, value-to-missing and value-to-different-value transitions, respectively. The percentage of changed cells uses the `editable_cells` denominator calculated by the report, not all cells in the original questionnaire. Quantitative/qualitative classifications are inferred from routing metadata and the classes of the prepared columns. Text may already have been converted to indicators: `string_variables = 0` does not show that the original questionnaire contained no open-ended questions. A numeric identifier can be classified as quantitative while retaining the separate RECORD_ID role. When comparing runs, retain inputs, seed, controls, donors and immutable variables. Changing the stratification variable with `freeze_strata = TRUE` also changes the automatically frozen variable. Similar change counts do not imply identical imputed values. Compare correction time separately from total elapsed time and cache reuse. The five STRATUM codes are listed in [Record correction](correzione-06.html). # Denominator and post-hoc uncertainty `editable_cells` equals the number of distinct processed record identifiers multiplied by the number of columns whose role is not RECORD_ID and whose `immutable` flag is false in `variable_profile`. It is not restricted to active questions or base variables: derived or mode-locked columns can enter unless marked immutable. `changed_cell_percentage` is 100 * cells_changed / editable_cells; a zero denominator produces NA. Use the same variable representation and immutable settings in comparisons. For a changed qualitative BASE variable that was not blanked, and when donor data are supplied, the report reconstructs a distribution at the final corrected record. `selected_probability` is the mass of the chosen value; `entropy` is -sum(p * log(p)) using natural logarithms. Normalized entropy divides by log(K), where K is the positive-probability support size, and is zero when K <= 1. These are post-hoc distribution summaries, not confidence intervals, correctness probabilities or the logged probabilities of the actual correction proposals. The reconstruction does not restore supplied user priors or domain overrides, so do not interpret it as an exact replay of runs using those settings. Inspect `status` and `distribution_source`. Quantitative changes receive structural-action labels instead of categorical entropy. `NOT_APPLICABLE` and unavailable distributions are not zero uncertainty.