Assembles the metadata tables that describe a submission - datasets, variables, codelists, computational methods and comments - into a validated define21_spec object ready for write_define() and check_define().

define_spec(
  datasets,
  variables,
  codelists = NULL,
  methods = NULL,
  comments = NULL,
  value_levels = NULL,
  where_clauses = NULL,
  external_codelists = NULL,
  study = "STUDY",
  standard = c(name = "SDTMIG", type = "IG", version = "3.4")
)

Arguments

datasets

A data frame, one row per dataset. Required columns dataset (name, e.g. "DM"), label, class (e.g. "SPECIAL PURPOSE", "FINDINGS", "ADAM OTHER") and structure (e.g. "One record per subject"). Optional: purpose ("Tabulation"/"Analysis", default "Tabulation"), repeating and is_reference_data ("Yes"/"No"), domain, archive_location (the shipped file name, default <dataset>.xpt in lower case) and comment (a key of comments).

variables

A data frame, one row per variable. Required columns dataset, variable, label, type (one of define_types()) and length. Optional: order (defaults to the order of the rows within the dataset), mandatory ("Yes"/"No", default "No"), key_sequence, role, codelist (a key of codelists), method (a key of methods), comment (a key of comments), origin (one of "Collected", "Derived", "Assigned", "Protocol", "Predecessor"), origin_description and display_format.

codelists

A data frame, one row per codelist term, or NULL. Required columns codelist (the key referenced by variables$codelist) and code (the coded value found in the data). Optional: name (the human readable codelist name, defaults to the key), decode, type (default "text") and order. A codelist with any decode is written as CodeListItem, one with none as EnumeratedItem.

methods

A data frame, one row per derivation method, or NULL. Required columns method (the key) and description. Optional: name, type ("Computation", "Imputation" or "Transpose"), expression and context (the language of expression, default "R").

comments

A data frame, one row per comment, or NULL. Required columns comment (the key) and description.

value_levels

A data frame of value level metadata, one row per value of one variable, or NULL. Required columns dataset, variable (the variable the values belong to, which must be declared in variables), value (the key that names this value, e.g. a VSTESTCD such as "SYSBP"), where_clause (a key of where_clauses), label, type and length. Optional columns are the same as for variables less key_sequence: order, mandatory, role, codelist, method, comment, origin, origin_description, display_format. Each row becomes an ItemDef of its own plus an ItemRef inside the variable's def:ValueListDef.

where_clauses

A data frame of value level conditions, one row per compared value, or NULL. Required columns where_clause (the key), dataset and variable (the variable the condition tests, which must be declared in variables - this is the check that stops a def:WhereClauseDef from being emitted against an ItemOID that does not exist), comparator (one of LT, LE, GT, GE, EQ, NE, IN, NOTIN) and check_value. Optional: soft_hard ("Soft"/"Hard", default "Soft") and comment. Consecutive rows sharing dataset, variable, comparator and soft_hard become one RangeCheck with several CheckValue children, which is how IN ('A', 'B') is written.

external_codelists

A data frame of codelists whose terms live in a dictionary rather than in the document, one row per codelist, or NULL. Required columns codelist (a key referenced by variables$codelist or value_levels$codelist, and distinct from every key of codelists), dictionary (e.g. "MedDRA", "WHODrug", "CDISC SDTM Controlled Terminology") and version (e.g. "26.1", "2025-03-28"). Optional: name (defaults to the key), type (default "text"), href and ref.

study

Study name. Used as the StudyName, StudyDescription, ProtocolName and study OID of the emitted document.

standard

Named character vector describing the standard the metadata follows, with elements name, type and version.

Value

An object of class define21_spec: a list with elements datasets, variables, codelists, methods, comments, value_levels, where_clauses, external_codelists (tibbles in canonical column order), study and standard.

Details

This is the pure-R replacement for maintaining define metadata in a spreadsheet and running a SAS macro (or a commercial tool) over the export: every reference between the tables is resolved here, at the boundary, and every problem is reported at once instead of one per run.

Any column not listed below is dropped, so that a specification written with write_define() and read back with read_define() compares equal.

Examples

p <- system.file("extdata", package = "define21")
csv <- function(f) utils::read.csv(file.path(p, f), na.strings = "")
spec <- define_spec(
  datasets           = csv("datasets.csv"),
  variables          = csv("variables.csv"),
  codelists          = csv("codelists.csv"),
  methods            = csv("methods.csv"),
  comments           = csv("comments.csv"),
  value_levels       = csv("value_levels.csv"),
  where_clauses      = csv("where_clauses.csv"),
  external_codelists = csv("external_codelists.csv")
)
spec
#> 
#> ── Define-XML 2.1 specification ────────────────────────────────────────────────
#>  Study: STUDY | standard: SDTMIG 3.4 (IG)
#>  3 dataset(s), 28 variable(s), 9 codelist(s), 2 method(s), 1 comment(s)
#>  6 value(s) across 2 value list(s), 3 where clause(s), 2 external codelist(s)
#>  [DM] Demographics - 10 variable(s), One record per subject
#>  [AE] Adverse Events - 10 variable(s), One record per adverse event per subject
#>  [VS] Vital Signs - 8 variable(s), One record per vital sign measurement per subject
spec$variables[1:3, c("dataset", "variable", "type", "length")]
#> # A tibble: 3 × 4
#>   dataset variable type  length
#>   <chr>   <chr>    <chr>  <int>
#> 1 DM      STUDYID  text      10
#> 2 DM      DOMAIN   text       2
#> 3 DM      USUBJID  text      20
spec$value_levels[, c("variable", "value", "where_clause", "length", "codelist")]
#> # A tibble: 6 × 5
#>   variable value where_clause length codelist 
#>   <chr>    <chr> <chr>         <int> <chr>    
#> 1 VSSTRESN SYSBP VS_SYSBP          5 NA       
#> 2 VSSTRESN DIABP VS_DIABP          5 NA       
#> 3 VSSTRESN PULSE VS_PULSE          5 NA       
#> 4 VSSTRESU SYSBP VS_SYSBP          4 VSRESU_BP
#> 5 VSSTRESU DIABP VS_DIABP          4 VSRESU_BP
#> 6 VSSTRESU PULSE VS_PULSE          9 VSRESU_HR
spec$where_clauses[, c("where_clause", "variable", "comparator", "check_value")]
#> # A tibble: 3 × 4
#>   where_clause variable comparator check_value
#>   <chr>        <chr>    <chr>      <chr>      
#> 1 VS_SYSBP     VSTESTCD EQ         SYSBP      
#> 2 VS_DIABP     VSTESTCD EQ         DIABP      
#> 3 VS_PULSE     VSTESTCD EQ         PULSE