| Title: | Generate Analysis Results Programmes Using ARS Metadata |
|---|---|
| Description: | Analysis Results Standard (ARS), a foundational standard by CDISC (Clinical Data Interchange Standards Consortium), provides a logical data model for metadata describing all components to calculate Analysis Results. <https://www.cdisc.org/standards/foundational/analysis-results-standard> Using 'siera', ARS metadata is ingested (JSON format), producing R programmes to generate Analysis Results Datasets (ARDs). Supports arbitrary-depth table structures, multi-value conditions, data-driven groupings, and CDISC-compliant ARD column stamping. |
| Authors: | Malan Bosman [aut, cre], Clymb Clinical [cph, fnd] |
| Maintainer: | Malan Bosman <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.5.6 |
| Built: | 2026-10-15 12:06:40 UTC |
| Source: | https://github.com/clymbclinical/siera |
siera comes bundled with some example ARD-producing scripts in its 'inst/script' directory. This function make them easy to access.
ARD_script_example(path = NULL)ARD_script_example(path = NULL)
path |
Name of R file. If 'NULL', the example files will be listed. |
A list of example R files (if path is NULL), or a file itself if path is used.
ARD_script_example() ARD_script_example("ARD_Out14-1-1.R")ARD_script_example() ARD_script_example("ARD_Out14-1-1.R")
siera comes bundled with some example files in its 'inst/extdata' directory. This function make them easy to access.
ARS_example(path = NULL)ARS_example(path = NULL)
path |
Name of file. If 'NULL', the example files will be listed. |
A list of example files (if path is NULL), or a file itself if path is used.
ARS_example() ARS_example("Common_Safety_Displays_cards.json")ARS_example() ARS_example("Common_Safety_Displays_cards.json")
Builds a small, validated description of one entry of an analysis' 'orderedGroupings', so that [ars_stamp()] can add the CDISC ARD columns 'group<n>_groupingId', 'group<n>_groupId' and (for data-driven groupings) 'group<n>_groupValue'. siera calls this function in the scripts it generates, with the values copied from the ARS metadata - each argument maps to one ARS element:
ars_grouping(id, groups = NULL, data_driven = FALSE)ars_grouping(id, groups = NULL, data_driven = FALSE)
id |
Grouping id: a single, non-empty string ('analyses[].orderedGroupings[].groupingId'). |
groups |
Optional named character vector describing the pre-defined groups of a non-data-driven grouping. Names are group ids ('analysisGroupings[].groups[].id'), values the matching condition values ('analysisGroupings[].groups[].condition.value'). 'NULL' (default) means the grouping defines no groups. |
data_driven |
Single logical, 'analysisGroupings[].dataDriven'. Defaults to 'FALSE'. |
| Argument | ARS JSON path | Notes |
| `id` | `analyses[].orderedGroupings[].groupingId` (= `analysisGroupings[].id`) | Written to `group<n>_groupingId`. |
| `groups` | `analysisGroupings[].groups[]` | Names are the group ids (`groups[].id`), values the group condition values (`groups[].condition.value`). An `IN` condition repeats the name once per value. |
| `data_driven` | `analysisGroupings[].dataDriven` | When `TRUE` the groups are discovered from the data, so `groups` must be empty. |
An object of class 'siera_ars_grouping', to be supplied in the 'groupings' list of [ars_stamp()].
[ars_stamp()]
# A pre-defined grouping (e.g. treatment arms) ars_grouping( "AnlsGrouping_01_Trt", groups = c( "AnlsGrouping_01_Trt_1" = "Placebo", "AnlsGrouping_01_Trt_2" = "Xanomeline Low Dose" ) ) # A data-driven grouping (categories are discovered from the data) ars_grouping("AnlsGrouping_04_AEBODSYS", data_driven = TRUE)# A pre-defined grouping (e.g. treatment arms) ars_grouping( "AnlsGrouping_01_Trt", groups = c( "AnlsGrouping_01_Trt_1" = "Placebo", "AnlsGrouping_01_Trt_2" = "Xanomeline Low Dose" ) ) # A data-driven grouping (categories are discovered from the data) ars_grouping("AnlsGrouping_04_AEBODSYS", data_driven = TRUE)
The last step of every analysis in a siera-generated ARD script: it takes the ARD that the analysis method computed (typically a cards object) and links it back to the ARS metadata by adding the CDISC ARD identifier columns:
ars_stamp(ard, analysis_id, method_id, output_id, groupings = list())ars_stamp(ard, analysis_id, method_id, output_id, groupings = list())
ard |
The ARD computed by the analysis method: a data frame (typically a cards object), or 'NULL' when the analysis had no data. |
analysis_id |
Analysis id: a single string ('analyses[].id'). |
method_id |
Method id: a single string ('analyses[].methodId'). |
output_id |
Output id: a single string (the 'outputId' of the 'mainListOfContents' list item the analysis belongs to). |
groupings |
A list of [ars_grouping()] objects ('analyses[].orderedGroupings[]'). The position in the list is the ARD group number: the first grouping is stamped onto 'group1_*', the second onto 'group2_*', and so on. Each needs the matching 'group<n>_level' column in 'ard'. Default: no groupings. |
* 'AnalysisId', 'MethodId' and 'OutputId'; * for each grouping, 'group<n>_groupingId' plus either 'group<n>_groupId' (pre-defined groups, looked up from the 'group<n>_level' column) or 'group<n>_groupValue' (data-driven groupings); * all '*_level' columns are coerced to character, so ARDs of different analyses can be row-bound safely.
When 'ard' is 'NULL' - the analysis had no data, so the method was skipped - a statistics-free stub row carrying only 'AnalysisId', 'MethodId' and 'OutputId' is returned.
siera calls this function in the scripts it generates, with the values copied from the ARS metadata - each argument maps to one ARS element:
| Argument | ARS JSON path | ARD column(s) |
| `ard` | result of the analysis method (`methods[].codeTemplate`) | (input) |
| `analysis_id` | `analyses[].id` | `AnalysisId` |
| `method_id` | `analyses[].methodId` | `MethodId` |
| `output_id` | `mainListOfContents` list item `outputId` | `OutputId` |
| `groupings` | `analyses[].orderedGroupings[]` | `group<n>_groupingId`, `group<n>_groupId`, `group<n>_groupValue` |
'ard' with the identifier columns added (a 'data.frame' stub when 'ard' is 'NULL').
[ars_grouping()], [readARS()]
# A tiny ARD, as an analysis method might return it ard <- tibble::tibble( group1_level = c("Placebo", "Xanomeline Low Dose"), stat_name = "n", stat = list(86L, 84L) ) ars_stamp( ard, analysis_id = "An_01", method_id = "Mth_01", output_id = "Out_01", groupings = list( ars_grouping( "AnlsGrouping_01_Trt", groups = c( "AnlsGrouping_01_Trt_1" = "Placebo", "AnlsGrouping_01_Trt_2" = "Xanomeline Low Dose" ) ) ) ) # No data: a stub row identifying the analysis is returned ars_stamp(NULL, "An_01", "Mth_01", "Out_01")# A tiny ARD, as an analysis method might return it ard <- tibble::tibble( group1_level = c("Placebo", "Xanomeline Low Dose"), stat_name = "n", stat = list(86L, 84L) ) ars_stamp( ard, analysis_id = "An_01", method_id = "Mth_01", output_id = "Out_01", groupings = list( ars_grouping( "AnlsGrouping_01_Trt", groups = c( "AnlsGrouping_01_Trt_1" = "Placebo", "AnlsGrouping_01_Trt_2" = "Xanomeline Low Dose" ) ) ) ) # No data: a stub row identifying the analysis is returned ars_stamp(NULL, "An_01", "Mth_01", "Out_01")
**Deprecated.** siera is moving to JSON-only ARS metadata, and both '.xlsx' input to [readARS()] and this converter will be removed in a future release. Use it now to convert each workbook once, then keep the '.json' file as the source of truth for your ARS metadata. Every call warns with class 'siera_deprecated_xlsx'.
Converts a CDISC Analysis Results Standard (ARS) metadata workbook ('.xlsx') into an ARS ReportingEvent JSON file. This is an R-native reimplementation of CDISC's Python 'excel2ars.py' utility and performs a faithful whole-workbook conversion: every ARS worksheet is mapped, not only the sheets that [readARS()] itself consumes.
ars_xlsx_to_json(xlsx_path, json_path = NULL)ars_xlsx_to_json(xlsx_path, json_path = NULL)
xlsx_path |
Path to the ARS Excel workbook ('.xlsx'). |
json_path |
Optional path for the output JSON file. When 'NULL' (the default), the JSON is written beside 'xlsx_path' with the same base name and a '.json' extension. |
The converter maps the full ARS object model: 'about', 'studyInfo', the main and other lists of contents, reference documents, terminology extensions, analysis output categorizations, analysis sets, analysis groupings, data subsets, methods (with operations and code templates), analyses, global display sections and outputs (with displays).
Multi-value cells (for example the values of an 'IN' condition, or 'categoryIds') are split on '|', with or without surrounding spaces, and each value is trimmed. Commas are never treated as separators. Multi-value ARS fields are always written as JSON arrays, even when they hold one value.
Note that the ARS spec evolves; this converter targets the worksheet layout emitted by TFL Designer and the CDISC ARS template and may need updating for future ARS versions.
The path to the written JSON file, invisibly.
json <- suppressWarnings( ars_xlsx_to_json(ARS_example("exampleARS_6.xlsx"), json_path = tempfile(fileext = ".json")) ) readARS(json, output_path = tempdir(), adam_path = tempdir())json <- suppressWarnings( ars_xlsx_to_json(ARS_example("exampleARS_6.xlsx"), json_path = tempfile(fileext = ".json")) ) readARS(json, output_path = tempdir(), adam_path = tempdir())
siera ships a plain-text library of analysis-method code templates (the 'templateCode' + parameters + valueSource recipes that drive ARD generation) under 'inst/method-library'. This accessor lists the available methods and resolves the on-disk location of a method's files, so you do not have to call [system.file()] directly. Each method's stable 'id' is the key intended for an ARS file to reference.
method_library(id = NULL)method_library(id = NULL)
id |
Method id (e.g. '"risk_difference"'). If 'NULL' (default), the available method ids are returned. |
The human-readable catalog ('METHODS.md') and the valueSource registry ('constructs.json') live at the library root, i.e. 'system.file("method-library", package = "siera")'.
When 'id' is 'NULL', a character vector of available method ids. Otherwise, the path to that method's directory (containing 'method.json' and 'template.R').
method_library() method_library("risk_difference")method_library() method_library("risk_difference")
Ingest ARS (Analysis Results Standard) metadata, and meta-programme R scripts that could be run as-is to produce Analysis Results Datasets when ingesting ADaM datasets
readARS( ARS_path, output_path = tempdir(), adam_path = tempdir(), spec_output = "", output_format = "none", code_style = "wrapped", column_labels = NULL )readARS( ARS_path, output_path = tempdir(), adam_path = tempdir(), spec_output = "", output_format = "none", code_style = "wrapped", column_labels = NULL )
ARS_path |
A file containing ARS metadata for a reporting event |
output_path |
Path to store .R ARD scripts |
adam_path |
Path to folder containing ADaM datasets, to be run in
ARD program. Datasets may be supplied as CSV ('.csv'), SAS transport
('.xpt') or CDISC Dataset-JSON ('.json') files. siera chooses the reader
for each dataset from the file extension found in this folder — '.csv'
files are read with |
spec_output |
The output ID for a specific output to be run from the metadata |
output_format |
Format for emitting the generated ARD. Must be exactly one of '"none"' or '"datasetjson"' (no partial matching). '"none"' (default) generates the ARD scripts only. '"datasetjson"' additionally appends code that writes each ARD as a CDISC Dataset-JSON file ('ARD_<OutputId>.json') when the generated script is run. The Dataset-JSON export requires the optional datasetjson package to be installed in the environment that runs the generated script. |
code_style |
Style of the generated analysis code. Must be exactly one
of '"wrapped"' or '"expanded"' (no partial matching). '"wrapped"' (default)
ends each analysis with a call to |
column_labels |
Optional named character vector of Dataset-JSON variable labels, e.g. 'c(AGEGR1 = "Pooled Age Group 1", TRT01A = "Actual Treatment")'. Names are ARD column names and values are the labels to write. Overrides take precedence over siera's built-in label dictionary, so they can also reword built-in labels. Because the ARD's columns are only known once the generated script runs, a name that matches no ARD column triggers a warning at script runtime (likely a typo) rather than an error. Only used when 'output_format = "datasetjson"'; otherwise it is ignored with a warning. |
R programmes generating ARDs - one for each output (or analysis from an output) specified in the ARS metadata
# path to file containing ARS metadata ARS_path <- ARS_example("Common_Safety_Displays_cards.json") # output path for R programs output_dir <- tempdir() # folder containing ADaM datasets adam_folder <- tempdir() # run function, write to temp directory readARS(ARS_path, output_dir, adam_folder)# path to file containing ARS metadata ARS_path <- ARS_example("Common_Safety_Displays_cards.json") # output path for R programs output_dir <- tempdir() # folder containing ADaM datasets adam_folder <- tempdir() # run function, write to temp directory readARS(ARS_path, output_dir, adam_folder)