# Let's warm-up!
library(dplyr)
# Using dplyr:
# - From the ADSL dataset:
# - Subset to the safety population (SAFFL == "Y")
# - calculate the number of unique subjects in each treatment group (TRT01A)
pharmaverseadam::adsl |>
filter( ) |>
count( )
Exercises
Exercises
00-warmup.R
01-cards-partA.R
# ARD Exercise: Demographic summaries using {cards}
# For this exercise, compute all the necessary summaries for a demographics table that includes age, age group, sex, race, ethnicity, bmi, height, and weight. We want to compute these summaries within each treatment group (High Dose, Low Dose, Placebo) and overall.
# Setup
## Load necessary packages
library(cards)
library(dplyr)
library(tidyr)
## Import data
adsl <- pharmaverseadam::adsl |>
filter(SAFFL == "Y") |>
left_join(
pharmaverseadam::advs |>
filter(PARAMCD %in% c("BMI", "HEIGHT", "WEIGHT"), !is.na(AVAL)) |>
group_by(USUBJID, PARAMCD) |>
arrange(ADY) |>
slice(1) |>
ungroup() |>
select(USUBJID, PARAMCD, AVAL) |>
pivot_wider(names_from = PARAMCD, values_from = AVAL),
by = "USUBJID"
)
## A. First, compute the continuous summaries for AGE, BMI, HEIGHT, WEIGHT by TRT01A
ard_continuous(
data = adsl,
by = ,
variables =
)
## B. Next, compute the categorical summaries for AGEGR1, SEX, RACE, ETHNIC by TRT01A
ard_categorical(
data = adsl,
by = ,
variables =
)
## C. Perform all of the summaries in a single ard_stack() call, including:
# - summaries by TRT01A as performed above
# - continuous summaries from part A for AGE, BMI, HEIGHT, and WEIGHT
# - categorical summaries from part B for AGEGR1, SEX, RACE, ETHNIC
ard_stack(
data = adsl,
.by = ,
# add ard_* calls here
)
## D. BONUS!
# For part C. above, add the following pieces
# - overall summaries for all of the variables
# - total N
# (Hint: Modify the `.overall` and `.total_n` arguments, respectively)
01-cards-partB.R
# Exercise: Adverse Events summaries using {cards}
# Load necessary packages
library(cards)
# Import data
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
adae <- pharmaverseadam::adae
# Exercise:
# A. Calculate the number and percentage of *unique* subjects with at least one AE:
# - Overall
# - By each SOC (AESOC)
# - By each Preferred term (AEDECOD) within SOC (AESOC)
# By every combination of treatment group (TRT01A) and severity (AESEV)
ard_stack_hierarchical(
data = ,
variables = ,
by = ,
id = ,
denominator = ,
over_variables =
)
02-cardx.R
# ARD Exercise: Demographic comparison with {cardx}
# In a previous exercise, you calculated summary deomgraphic statistics by treament arm
# Here, we will use a subset of those variables, and compare their values across treatment arms
# Variables: AGE, SEX, RACE
# Treatment variable: TRT01A
# Compare AGE with the Kruskal-Wallis test and SEX and AGE with Pearson's Chi-square test
# DISCLAIMER: Don't compare baseline characteristics in randomized trials in real life!
# Setup
## Import data
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
## A. First, compute the Kruskal-Wallis test for AGE by TRT01A
kruskal_ard <-
cardx::ard_stats_kruskal_test(
data = ,
by = ,
variables =
)
## B. First, compute the Chi-squared test for SEX, RACE by TRT01A
chisq_ard <-
cardx::ard_stats_chisq_test(
data = ,
by = ,
variables =
)
## C. Combine your results with `cards::bind_ard()` and subset the ARD to include the rows with p-values only
final_ard <-
cards::bind_ard(
) |>
dplyr::filter()
## Bonus. Which test returned a warning? If any, print the warning.
## Note that the warning column is a list-column which requires special handling
03-gtsummary-partA.R
# ARD Exercise: Demographic summary table using {gtsummary}
# For this exercise, create a summary table using `tbl_summary()`
# 1. Split summary statistics by TRT01A
# 2. Include AGE, SEX, and RACE. For AGE, display the "mean (sd)" and "median (p25, p75)" on separate rows
# HINT: Use `type = AGE ~ 'continuous2'` and `statistic = AGE ~ c("{mean} ({sd})", "{median} ({p25}, {p75})")`
# 3. Include a column of overall results using `add_overall()`
# BONUS: Use `cards::gather_ard()` to extract the ARD from the table object
# Setup
## Import data
library(gtsummary)
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
# Create table
tbl <- adsl |>
tbl_summary(
by = ,
include = ,
type = ,
statistic =
) |>
add_overall()
tbl
# Extract ARD from tbl object
03-gtsummary-partB.R
# ARD Exercise: Demographic summary table using {cards}+{gtsummary}
# For this exercise, create a summary table using `tbl_ard_summary()`
# 1. Split summary statistics by TRT01A
# 2. Include AGE, SEX, and RACE. For AGE, display the "mean (sd)" and "median (p25, p75)" on separate rows
# HINT: Use `type = AGE ~ 'continuous2'` and `statistic = AGE ~ c("{mean} ({sd})", "{median} ({p25}, {p75})")`
# 3. Include a column of overall results using `tbl_ard_summary(overall=TRUE)`
# Setup
## Import data
library(cards)
library(gtsummary)
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
# Create the ARD with the needed statistics
ard <-
ard_stack(
adsl,
.by = TRT01A,
ard_continuous(variables = AGE),
ard_categorical(variables = c(SEX, RACE)),
.attributes = TRUE,
.overall = TRUE
)
# Create table
ard |>
tbl_ard_summary(
by = ,
include = ,
type = ,
statistic = ,
overall =
)
04-tables-tfrmt.R
# Setup - Modifying a table with {tfrmtbuilder} --------------------------------
# Load libraries
library(tfrmtbuilder)
library(tfrmt)
# Import ARD and tfrmt
ard_demog <- readRDS("exercises/data/ard_demog.rds")
tfrmt_demog <- json_to_tfrmt("exercises/data/tfrmt_demog.json")
# Run app
tfrmtbuilder(
tfrmt = tfrmt_demog,
data = ard_demog,
mockmode = FALSE # to create table with values
)
# Exercise - Modifying a table with {tfrmtbuilder} -----------------------------
# 1. Switch the order of treatment columns so Active is first
# (hint: Column Plan)
# 2. Change the footnote marks to letters instead of numbers
# (hint: Footnote Plan)
# 3. Split the table into 2 parts by setting a maximum of 3 rows
# (hint: Page Plan)
# 4. Export table (hint: Export tab)
Solutions
00-warmup-answer-answer.R
# Let's warm-up!
library(dplyr)
# Using dplyr:
# - From the ADSL dataset:
# - Subset to the safety population (SAFFL == "Y")
# - calculate the number of unique subjects in each treatment group (TRT01A)
pharmaverseadam::adsl |>
filter(SAFFL == "Y") |>
count(TRT01A)
01-cards-partA-answer.R
# ARD Exercise: Demographic summaries using {cards}
# For this exercise, compute all the necessary summaries for a demographics table that includes age, age group, sex, race, ethnicity, bmi, height, and weight. We want to compute these summaries within each treatment group (High Dose, Low Dose, Placebo) and overall.
# Setup
## Load necessary packages
library(cards)
library(dplyr)
library(tidyr)
## Import data
adsl <- pharmaverseadam::adsl |>
filter(SAFFL == "Y") |>
left_join(
pharmaverseadam::advs |>
filter(PARAMCD %in% c("BMI", "HEIGHT", "WEIGHT"), !is.na(AVAL)) |>
group_by(USUBJID, PARAMCD) |>
arrange(ADY) |>
slice(1) |>
ungroup() |>
select(USUBJID, PARAMCD, AVAL) |>
pivot_wider(names_from = PARAMCD, values_from = AVAL),
by = "USUBJID"
)
## A. First, compute the continuous summaries for AGE, BMI, HEIGHT, WEIGHT by TRT01A
ard_continuous(
data = adsl,
by = TRT01A,
variables = c(AGE, BMI, HEIGHT, WEIGHT)
)
## B. Next, compute the categorical summaries for AGEGR1, SEX, RACE, ETHNIC by TRT01A
ard_categorical(
data = adsl,
by = TRT01A,
variables = c(AGEGR1, SEX, RACE, ETHNIC)
)
## C. Perform all of the summaries in a single ard_stack() call, including:
# - summaries by TRT01A as performed above
# - continuous summaries from part A for AGE, BMI, HEIGHT, and WEIGHT
# - categorical summaries from part B for AGEGR1, SEX, RACE, ETHNIC
ard_stack(
data = adsl,
.by = TRT01A,
ard_continuous( variables = c(AGE, BMI, HEIGHT, WEIGHT)),
ard_categorical(variables = c(AGEGR1, SEX, RACE, ETHNIC))
)
## D. BONUS!
# For part C. above, add the following pieces
# - overall summaries for all of the variables
# - total N
# (Hint: Modify the `.overall` and `.total_n` arguments, respectively)
ard_stack(
data = adsl,
.by = TRT01A,
ard_continuous( variables = c(AGE, BMI, HEIGHT, WEIGHT)),
ard_categorical(variables = c(AGEGR1, SEX, RACE, ETHNIC)),
.overall = TRUE,
.total_n = TRUE
)
01-cards-partB-answer.R
# Exercise: Adverse Events summaries using {cards}
# Load necessary packages
library(cards)
# Import data
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
adae <- pharmaverseadam::adae
## A. Calculate the number and percentage of *unique* subjects (USUBJID) with at least one AE:
# - Overall
# - By each SOC (AESOC)
# - By each Preferred term (AEDECOD) within SOC (AESOC)
# By every combination of treatment group (TRT01A) and severity (AESEV)
ard_stack_hierarchical(
data = adae,
variables = c(AESOC, AEDECOD),
by = c(TRT01A, AESEV),
id = USUBJID,
denominator = adsl,
over_variables = TRUE
)
02-cardx-answer.R
# ARD Exercise: Demographic comparison with {cardx}
# In a previous exercise, you calculated summary deomgraphic statistics by treament arm
# Here, we will use a subset of those variables, and compare their values across treatment arms
# Variables: AGE, SEX, RACE
# Treatment variable: TRT01A
# Compare AGE with the Kruskal-Wallis test and SEX and AGE with Pearson's Chi-square test
# DISCLAIMER: Don't compare baseline characteristics in randomized trials in real life!
# Setup
## Import data
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
## A. First, compute the Kruskal-Wallis test for AGE by TRT01A
kruskal_ard <-
cardx::ard_stats_kruskal_test(
data = adsl,
by = TRT01A,
variables = AGE
)
## B. First, compute the Chi-squared test for SEX, RACE by TRT01A
chisq_ard <-
cardx::ard_stats_chisq_test(
data = adsl,
by = TRT01A,
variables = c(SEX, RACE)
)
## C. Combine your results with `cards::bind_ard()` and subset the ARD to include the rows with p-values only
final_ard <-
cards::bind_ard(
kruskal_ard,
chisq_ard
) |>
dplyr::filter(stat_name == "p.value")
## Bonus. Which test returned a warning? If any, print the warning.
## Note that the warning column is a list-column which requires special handling
final_ard |> cards::print_ard_conditions()
final_ard |>
dplyr::filter(purrr::map_lgl(warning, Negate(is.null))) |>
as.data.frame()
03-gtsummary-partA-answer.R
# ARD Exercise: Demographic summary table using {gtsummary}
# For this exercise, create a summary table using `tbl_summary()`
# 1. Split summary statistics by TRT01A
# 2. Include AGE, SEX, and RACE. For AGE, display the "mean (sd)" and "median (p25, p75)" on separate rows
# HINT: Use `type = AGE ~ 'continuous2'` and `statistic = AGE ~ c("{mean} ({sd})", "{median} ({p25}, {p75})")`
# 3. Include a column of overall results using `add_overall()`
# BONUS: Use `cards::gather_ard()` to extract the ARD from the table object
# Setup
## Import data
library(gtsummary)
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
# Create table
tbl <- adsl |>
tbl_summary(
by = TRT01A,
include = c(AGE, SEX, RACE),
type = AGE ~ 'continuous2',
statistic = AGE ~ c("{mean} ({sd})", "{median} ({p25}, {p75})")
) |>
add_overall()
tbl
# Extract ARD from tbl object
gather_ard(tbl)
03-gtsummary-partB-answer.R
# ARD Exercise: Demographic summary table using {cards}+{gtsummary}
# For this exercise, create a summary table using `tbl_ard_summary()`
# 1. Split summary statistics by TRT01A
# 2. Include AGE, SEX, and RACE. For AGE, display the "mean (sd)" and "median (p25, p75)" on separate rows
# HINT: Use `type = AGE ~ 'continuous2'` and `statistic = AGE ~ c("{mean} ({sd})", "{median} ({p25}, {p75})")`
# 3. Include a column of overall results using `tbl_ard_summary(overall=TRUE)`
# Setup
## Import data
library(cards)
library(gtsummary)
adsl <- pharmaverseadam::adsl |> dplyr::filter(SAFFL == "Y")
# Create the ARD with the needed statistics
ard <-
ard_stack(
adsl,
.by = TRT01A,
ard_continuous(variables = AGE),
ard_categorical(variables = c(SEX, RACE)),
.attributes = TRUE,
.overall = TRUE
)
# Create table
ard |>
tbl_ard_summary(
by = TRT01A,
include = c(AGE, SEX, RACE),
type = AGE ~ 'continuous2',
statistic = AGE ~ c("{mean} ({sd})", "{median} ({p25}, {p75})"),
overall = TRUE
)