The Analysis Results Dataset (ARD) is an emerging CDISC standard that stores statistical results in a tidy, machine-readable format - reusable across tables, figures, and reports without re-running analyses.
pharmaverseadam - reference ADaM datasets as input
2 Setup
library(cards)library(cardx)library(pharmaverseadam)library(dplyr)# Safety population from ADSLadsl_safe <- pharmaverseadam::adsl %>% dplyr::filter(SAFFL =="Y")cat("Safety population N:", nrow(adsl_safe), "\n")
Safety population N: 254
cat("Treatment arms:\n")
Treatment arms:
adsl_safe %>% dplyr::count(TRT01A)
# A tibble: 3 × 2
TRT01A n
<chr> <int>
1 Placebo 86
2 Xanomeline High Dose 72
3 Xanomeline Low Dose 96
3 Step 1: Confirm Available Variables
# Always verify before use - BMIBL is NOT in pharmaverseadam::adslnames(adsl_safe)
group1 group1_level variable stat_name stat_label stat
1 TRT01A Placebo AGE mean Mean 75.209
2 TRT01A Placebo AGE sd SD 8.59
3 TRT01A Placebo AGE median Median 76
4 TRT01A Placebo AGE p25 Q1 69
5 TRT01A Placebo AGE p75 Q3 82
6 TRT01A Placebo AGE min Min 52
7 TRT01A Placebo AGE max Max 89
8 TRT01A Xanomeli… AGE mean Mean 73.778
9 TRT01A Xanomeli… AGE sd SD 7.944
10 TRT01A Xanomeli… AGE median Median 75.5
group1 group1_level variable variable_level stat_name stat_label stat
1 TRT01A Placebo SEX F n n 53
2 TRT01A Placebo SEX F N N 86
3 TRT01A Placebo SEX F p % 0.616
4 TRT01A Placebo SEX M n n 33
5 TRT01A Placebo SEX M N N 86
6 TRT01A Placebo SEX M p % 0.384
7 TRT01A Placebo RACE AMERICAN… n n 0
8 TRT01A Placebo RACE AMERICAN… N N 86
9 TRT01A Placebo RACE AMERICAN… p % 0
10 TRT01A Placebo RACE BLACK OR… n n 8
11 TRT01A Placebo RACE BLACK OR… N N 86
12 TRT01A Placebo RACE BLACK OR… p % 0.093
6 Step 4: Missing Values ARD
# Note: keep ard_missing separate - do not combine with ard_cont/cat# (overlapping stat_names cause duplicates in bind_ard)ard_miss <- cards::ard_missing( adsl_safe,by = TRT01A,variables =c(AGE, SEX, RACE, AGEGR1, ETHNIC))ard_miss %>% dplyr::select(group1, group1_level, variable, stat_name, stat_label, stat)
group1 group1_level variable stat_name stat_label stat
1 TRT01A Placebo AGE N_obs Vector L… 86
2 TRT01A Placebo AGE N_miss N Missing 0
3 TRT01A Placebo AGE N_nonmiss N Non-mi… 86
4 TRT01A Placebo AGE p_miss % Missing 0
5 TRT01A Placebo AGE p_nonmiss % Non-mi… 1
6 TRT01A Placebo SEX N_obs Vector L… 86
7 TRT01A Placebo SEX N_miss N Missing 0
8 TRT01A Placebo SEX N_nonmiss N Non-mi… 86
9 TRT01A Placebo SEX p_miss % Missing 0
10 TRT01A Placebo SEX p_nonmiss % Non-mi… 1
group1 variable stat_name stat_label stat
1 TRT01A AGE estimate Mean Dif…
2 TRT01A AGE estimate1 Group 1 …
3 TRT01A AGE estimate2 Group 2 …
4 TRT01A AGE statistic t Statis…
5 TRT01A AGE p.value p-value
6 TRT01A AGE parameter Degrees …
7 TRT01A AGE conf.low CI Lower…
8 TRT01A AGE conf.high CI Upper…
9 TRT01A AGE method method
10 TRT01A AGE alternative alternat…
11 TRT01A AGE mu H0 Mean 0
12 TRT01A AGE paired Paired t… FALSE
13 TRT01A AGE var.equal Equal Va… FALSE
14 TRT01A AGE conf.level CI Confi… 0.95
group1 variable stat_name stat_label stat
1 TRT01A SEX statistic X-square… 2.761
2 TRT01A SEX p.value p-value 0.251
3 TRT01A SEX parameter Degrees … 2
4 TRT01A SEX method method Pearson'…
5 TRT01A SEX correct correct TRUE
6 TRT01A SEX p p rep, 1/length(x), length(x)
7 TRT01A SEX rescale.p rescale.p FALSE
8 TRT01A SEX simulate.p.value simulate… FALSE
9 TRT01A SEX B B 2000
group1 variable stat_name stat_label stat
1 TRT01A AGE statistic X-square…
2 TRT01A AGE p.value p-value
3 TRT01A AGE method method
4 TRT01A AGE alternative alternat…
5 TRT01A AGE mu mu 0
6 TRT01A AGE paired Paired t… FALSE
7 TRT01A AGE exact exact
8 TRT01A AGE correct correct TRUE
9 TRT01A AGE conf.int conf.int FALSE
10 TRT01A AGE conf.level CI Confi… 0.95
11 TRT01A AGE tol.root tol.root 0
12 TRT01A AGE digits.rank digits.r… Inf
10 Step 8: Combine Summary ARDs
# bind_ard() with .update = TRUE resolves duplicate stat_names across ARD objects# Keep inferential (t-test, chisq, wilcox) separate from descriptive (cont, cat)ard_descriptive <- cards::bind_ard( ard_cont, ard_cat,.update =TRUE)ard_inferential <- cards::bind_ard( ard_t, ard_chi, ard_wilcox,.update =TRUE)cat("Descriptive ARD rows:", nrow(ard_descriptive), "\n")
group1 group1_level variable stat_name stat_label stat
1 TRT01A Placebo AGE mean Mean 75.209
2 TRT01A Placebo AGE sd SD 8.59
3 TRT01A Placebo AGE median Median 76
4 TRT01A Placebo AGE p25 Q1 69
5 TRT01A Placebo AGE p75 Q3 82
6 TRT01A Placebo AGE min Min 52
7 TRT01A Placebo AGE max Max 89
8 TRT01A Xanomeli… AGE mean Mean 73.778
9 TRT01A Xanomeli… AGE sd SD 7.944
10 TRT01A Xanomeli… AGE median Median 75.5
11 TRT01A Xanomeli… AGE p25 Q1 70
12 TRT01A Xanomeli… AGE p75 Q3 79
13 TRT01A Xanomeli… AGE min Min 56
14 TRT01A Xanomeli… AGE max Max 88
15 TRT01A Xanomeli… AGE mean Mean 75.958
16 TRT01A Xanomeli… AGE sd SD 8.114
17 TRT01A Xanomeli… AGE median Median 78
18 TRT01A Xanomeli… AGE p25 Q1 71
19 TRT01A Xanomeli… AGE p75 Q3 82
20 TRT01A Xanomeli… AGE min Min 51
12 Step 10: Extract Specific Statistics
# Pull mean AGE per treatment armard_descriptive %>% dplyr::filter( variable =="AGE", stat_name =="mean", context =="continuous" ) %>% dplyr::select(group1_level, stat_name, stat) %>% dplyr::mutate(stat =round(unlist(stat), 1))
group1_level stat_name stat
1 Placebo mean 75.2
2 Xanomeli… mean 73.8
3 Xanomeli… mean 76
variable stat_name stat_label stat
1 AGE term term AGE
2 AGE var_label Label Age
3 AGE var_class Class numeric
4 AGE var_type Type continuo…
5 AGE label Level La… Age
6 AGE n_obs N Obs. 254
7 AGE n_event N Events 111
8 AGE estimate Coeffici… 0.983
9 AGE std.error Standard… 0.016
10 AGE statistic statistic -1.117
11 AGE p.value p-value 0.264
12 AGE conf.low CI Lower… 0.953
16 Step 14: Validation Checks
cat("\n=== ARD Validation ===\n\n")
=== ARD Validation ===
# Check 1: No error records in descriptive ARDcheck1 <- ard_descriptive %>% dplyr::filter(!sapply(error, is.null))cat("Check 1 - Descriptive ARD error records:", nrow(check1), "\n")
Check 1 - Descriptive ARD error records: 0
# Check 2: AGE mean stat is numericmean_stat <- ard_descriptive %>% dplyr::filter(variable =="AGE", stat_name =="mean", context =="continuous") %>% dplyr::pull(stat)check2 <-all(sapply(mean_stat, is.numeric))cat("Check 2 - AGE mean is numeric:", check2, "\n")
Check 2 - AGE mean is numeric: TRUE
# Check 3: SEX counts per treatment armcat_n <- ard_descriptive %>% dplyr::filter(variable =="SEX", stat_name =="n", context =="categorical") %>% dplyr::mutate(val =unlist(stat)) %>% dplyr::group_by(group1_level) %>% dplyr::summarise(total =sum(val), .groups ="drop")cat("Check 3 - SEX counts per arm:\n")