Produces the validation-findings table expected in a Reviewer's Guide: each finding with its severity, the number of records affected, and the sponsor's explanation where one is supplied. A finding with no explanation is flagged in needs_explanation and is never filled in for you, since an unexplained finding is what gets a submission questioned.

section_findings(findings, explanations = NULL)

Arguments

findings

A data frame in the schema above.

explanations

Optional sponsor explanations: a named character vector/list keyed by rule ID (or by message text), or a data frame with an explanation column plus a Rule ID or Message column. Rule ID is matched first, message text second. If NULL and findings already has an explanation column, that column is used.

Value

A tibble with dataset, variable, rule_id, message, records_affected, severity, explanation, needs_explanation, plus any other columns already in findings.

The findings contract

findings is a plain data frame in the Pinnacle 21 report column schema:

ColumnMeaning
Datasetdataset the finding is against, e.g. "AE"
Variablevariable(s) involved
Rule IDvalidator rule identifier, e.g. "SD0021"
Messagethe rule message
Records affectedhow many records the finding covers
Severity"Error", "Warning", "Notice", ...

Column names are matched case- and separator-insensitively, so Records affected, Records.affected (what read.csv() produces) and records_affected are all the same column, and the returned tibble uses the normalised snake_case names. Any other columns you supply are kept.

This is a data contract, not a package dependency: anything that emits these columns works — a Pinnacle 21 Excel/CSV export read with readxl::read_excel() or utils::read.csv(), a CDISC CORE run, or your own rule engine. reviewerguider deliberately does not import a validator package, so a change in one cannot break the other.

Examples

# Real Pinnacle 21 findings for the CDISCPILOT01 SDTM data.
findings <- read.csv(system.file("extdata", "findings.csv", package = "reviewerguider"))
explanations <- read.csv(system.file("extdata", "explanations.csv", package = "reviewerguider"))
section_findings(findings, explanations)
#> ! 3 finding(s) have no sponsor explanation and are flagged.
#> # A tibble: 6 × 8
#>   dataset   variable       rule_id message records_affected severity explanation
#>   <chr>     <chr>          <chr>   <chr>              <int> <chr>    <chr>      
#> 1 LB (LBHE) LBTEST, LBSTR… SD0029  Missin…             1000 Warning  NA         
#> 2 AE        AEENDTC        SD0021  Missin…              472 Warning  Adverse ev…
#> 3 LB (LBHE) LBORRES, LBTE… SD0026  Missin…              293 Warning  Original u…
#> 4 LB (LBUR) LBORRES, LBTE… SD0026  Missin…               25 Warning  Original u…
#> 5 DM        ARMCD, ACTARM… SD2236  ACTARM…               12 Warning  NA         
#> 6 QS (QSCO) QSSTRESC, QSB… SD1131  Missin…                7 Warning  NA         
#> # ℹ 1 more variable: needs_explanation <lgl>