Structural problems are caught when the shell is read. This checks the remaining class of problem – the one that only shows up at run time – by confronting the shell with a real dataset: variables that are referenced but absent, statistics requested for a variable of the wrong type, by-groups that end up empty after the population filter, and denominator datasets that were not supplied.

validate_shell(shell, data)

Arguments

shell

A shell2tlf_shell from read_shell() or new_shell().

data

A data frame, or a named list of data frames (see build_tlf()).

Value

A tibble with one row per problem and columns location (where in the shell), variable, severity ("error" or "warning") and message. Zero rows means the shell is ready to run.

Details

Run it in the dry-run step of a production program, before anyone waits on build_tlf(). It never throws for a data problem – it returns them all, so one pass tells you everything that needs fixing.

For a shift row it also counts the records whose baseline or post-baseline value is outside the shell's declared levels. Those records are excluded from the numerator and the denominator, so an unnoticed handful is exactly how a shift table stops reconciling with the population count in its own column header.

For a listing it checks the listed and sort variables and reports a population filter that would leave nothing to list.

This is the check a SAS programmer performs by eye, comparing the shell document against PROC CONTENTS output.

Examples

shell <- read_shell(system.file("extdata", "demographics.yaml",
                                package = "shell2tlf"))
adsl <- utils::read.csv(system.file("extdata", "adsl_demo.csv",
                                    package = "shell2tlf"))
validate_shell(shell, adsl)
#> # A tibble: 0 × 4
#> # ℹ 4 variables: location <chr>, variable <chr>, severity <chr>, message <chr>

# a variable the data does not have, and a mean of a character variable
broken <- shell
broken$rows[[1]]$var <- "AGEX"
broken$rows[[3]]$type <- "summary"
broken$rows[[3]]$stats <- "mean_sd"
validate_shell(broken, adsl)
#> # A tibble: 2 × 4
#>   location  variable severity message                                           
#>   <chr>     <chr>    <chr>    <chr>                                             
#> 1 rows[[1]] AGEX     error    Variable 'AGEX' is not in 'adsl'.                 
#> 2 rows[[3]] SEX      error    Summary statistics (mean_sd) requested for 'SEX',…

# a shift shell: records outside the declared levels are counted, because
# they leave both the numerator and the denominator
shift <- read_shell(system.file("extdata", "lab_shift.yaml",
                                package = "shell2tlf"))
adlb <- utils::read.csv(system.file("extdata", "adlb_demo.csv",
                                    package = "shell2tlf"))
validate_shell(shift, adlb)
#> # A tibble: 1 × 4
#>   location  variable severity message                                           
#>   <chr>     <chr>    <chr>    <chr>                                             
#> 1 rows[[1]] BNRIND   warning  1 of 230 records have a 'BNRIND' value outside th…