Evaluates each condition in a rules table (see pop_rules()) against the subject-level data and writes the result as a "Y"/"N" character flag. Rules are applied in order and each new flag is visible to later rules.

derive_pop_flags(adsl, rules)

Arguments

adsl

Subject-level data frame, e.g. ADSL.

rules

Rules table: a data frame with FLAG and CONDITION columns, or a pop_rules() object.

Value

A tibble::tibble: adsl with one character column per rule added (existing columns of the same name are overwritten), each "Y" or "N" and labelled if the rules table supplied a LABEL. A plain data frame, ready to hand on to admiral.

Details

A condition that cannot be evaluated, because it is not valid R, because it names a variable that does not exist, or because it does not return a logical vector, raises an error naming the flag. It never silently produces NA. A condition that evaluates to NA for some subjects, which is what AGE >= 18 does when age is missing, sets those subjects to "N" and warns with the count, because a population flag has to be "Y" or "N".

Replaces this SAS idiom

The %POPFLAG macro, or the study ADSL DATA step block of IF trtsdt NE . THEN saffl = 'Y'; ELSE saffl = 'N'; repeated once per population, where the definitions are buried in code rather than in a reviewable table. Here the same definitions live in a CSV that maps one-to-one onto the protocol's analysis populations. See sas_note().

Examples

adsl <- utils::read.csv(
  system.file("extdata", "adsl_example.csv", package = "admiralease")
)
rules <- utils::read.csv(
  system.file("extdata", "pop_rules.csv", package = "admiralease")
)

flagged <- derive_pop_flags(adsl, rules)
flagged[, c("USUBJID", "RANDFL", "SAFFL", "ITTFL", "EFFFL", "COMPLFL")]
#> # A tibble: 8 × 6
#>   USUBJID  RANDFL SAFFL ITTFL EFFFL COMPLFL
#>   <chr>    <chr>  <chr> <chr> <chr> <chr>  
#> 1 AE01-001 Y      Y     Y     Y     Y      
#> 2 AE01-002 Y      Y     Y     Y     N      
#> 3 AE01-003 Y      Y     Y     Y     Y      
#> 4 AE01-004 Y      Y     Y     N     Y      
#> 5 AE01-005 Y      N     Y     N     N      
#> 6 AE01-006 Y      Y     Y     Y     Y      
#> 7 AE01-007 N      N     N     N     N      
#> 8 AE01-008 Y      Y     Y     Y     N      

# A flag the protocol did not anticipate is just another row
derive_pop_flags(
  adsl,
  data.frame(FLAG = "ELDERFL", CONDITION = "AGE >= 65")
)$ELDERFL
#> ! ELDERFL: 1 subject where the condition is NA, set to "N".
#> [1] "N" "Y" "N" "N" "Y" "N" "N" "Y"