Skip to content

Commit

Permalink
Merge pull request #78 from ddsjoberg/gtsummary-demographics
Browse files Browse the repository at this point in the history
closes #53 Adding ARD demographics example
  • Loading branch information
rossfarrugia authored Sep 23, 2024
2 parents 29250e3 + ed1f4ec commit 0bd9051
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 63 deletions.
6 changes: 5 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ Authors@R:
person("Jeffrey", "Dickinson", role = "aut"),
person("Ege Can", "Taşlıçukur", role = "aut"),
person("Vedha", "Viyash", role = "aut"),
person("David", "Blair", role = "aut")
person("David", "Blair", role = "aut"),
person("Daniel D.", "Sjoberg", , "[email protected]", role = "aut", comment = c(ORCID = "0000-0003-0862-2018"))
Description: This is not a package, but we just use this file to declare
the dependencies of the site.
URL: https://github.com/pharmaverse/examples
Imports:
admiral,
cards,
dplyr,
gtsummary,
lubridate,
labelled,
magrittr,
metacore,
metatools,
Expand Down
81 changes: 57 additions & 24 deletions tlg/demographic.R
Original file line number Diff line number Diff line change
@@ -1,32 +1,65 @@
## ----r setup, message=FALSE, warning=FALSE, results='hold'--------------------
library(pharmaverseadam)
library(tern)
## ----r preproc----------------------------------------------------------------
library(dplyr)

adsl <- adsl %>%
df_explicit_na()

## ----r preproc----------------------------------------------------------------
# Create categorical variables
adsl <- adsl %>%
# Create categorical variables, remove screen failures, and assign column labels
adsl <- pharmaverseadam::adsl |>
filter(!ACTARM %in% "Screen Failure") |>
mutate(
SEX = factor(case_when(
SEX == "M" ~ "Male",
SEX == "F" ~ "Female",
SEX == "U" ~ "Unknown",
SEX == "UNDIFFERENTIATED" ~ "Undifferentiated"
)),
AGEGR1 = factor(
SEX = case_match(SEX, "M" ~ "MALE", "F" ~ "FEMALE"),
AGEGR1 =
case_when(
between(AGE, 18, 40) ~ "18-40",
between(AGE, 41, 64) ~ "41-64",
AGE > 64 ~ ">=65"
),
levels = c("18-40", "41-64", ">=65")
)
) |>
factor(levels = c("18-40", "41-64", ">=65"))
) |>
labelled::set_variable_labels(AGE = "Age (yr)",
AGEGR1 = "Age group",
SEX = "Sex",
RACE = "Race")

## ----r gtsummary-table--------------------------------------------------------
library(cards)
library(gtsummary)
theme_gtsummary_compact() # reduce default padding and font size for a gt table

# build the ARD with the needed summary statistics using {cards}
ard <-
ard_stack(
adsl,
ard_continuous(variables = AGE),
ard_categorical(variables = c(AGEGR1, SEX, RACE)),
.by = ACTARM, # split results by treatment arm
.attributes = TRUE # optionally include column labels in the ARD
)

## ----r table------------------------------------------------------------------
# use the ARD to create a demographics table using {gtsummary}
tbl_ard_summary(
cards = ard,
by = ACTARM,
include = c(AGE, AGEGR1, SEX, RACE),
type = AGE ~ "continuous2",
statistic = AGE ~ c("{N}", "{mean} ({sd})", "{median} ({p25}, {p75})", "{min}, {max}")
) |>
bold_labels() |>
modify_header(all_stat_cols() ~ "**{level}** \nN = {n}") |> # add Ns to header
modify_footnote(everything() ~ NA) # remove default footnote

## ----r gtsummary-ard----------------------------------------------------------
# build demographics table directly from a data frame
tbl <- adsl |> tbl_summary(by = ACTARM, include = c(AGE, AGEGR1, SEX, RACE))

# extract ARD from table object
gather_ard(tbl)[[1]] |> select(-gts_column) # removing column so ARD fits on page

## ----r rtables-setup, message=FALSE, warning=FALSE, results='hold'------------
library(tern)

adsl2 <- adsl |>
df_explicit_na()

## ----r rtables-table----------------------------------------------------------
vars <- c("AGE", "AGEGR1", "SEX", "RACE")
var_labels <- c(
"Age (yr)",
Expand All @@ -35,15 +68,15 @@ var_labels <- c(
"Race"
)

lyt <- basic_table(show_colcounts = TRUE) %>%
split_cols_by(var = "ACTARM") %>%
add_overall_col("All Patients") %>%
lyt <- basic_table(show_colcounts = TRUE) |>
split_cols_by(var = "ACTARM") |>
add_overall_col("All Patients") |>
analyze_vars(
vars = vars,
var_labels = var_labels
)

result <- build_table(lyt, adsl)
result <- build_table(lyt, adsl2)

result

131 changes: 93 additions & 38 deletions tlg/demographic.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -13,56 +13,111 @@ knitr::opts_chunk$set(echo = TRUE)

This guide will show you how pharmaverse packages, along with some from tidyverse, can be used to create a Demographic table, using the `{pharmaverseadam}` `ADSL` data as an input.

The packages used with a brief description of their purpose are as follows:

* [`{rtables}`](https://insightsengineering.github.io/rtables/): designed to create and display complex tables with R.
* [`{tern}`](https://insightsengineering.github.io/tern/): contains analysis functions to create tables and graphs used for clinical trial reporting.

## Load Data and Required pharmaverse Package

After installation of packages, the first step is to load our pharmaverse packages and input data. Here, we are going to encode missing entries in a data frame `adsl`.

Note that `{tern}` depends on `{rtables}` so the latter is automatically attached.
In the examples below, we illustrate two general approaches for creating a demographics table.
The first utilizes Analysis Results Datasets---part of the emerging [CDISC Analyis Results Standard](https://www.cdisc.org/standards/foundational/analysis-results-standard).
The second is the classic method of creating summary tables directly from a data set.

```{r setup, message=FALSE, warning=FALSE, results='hold'}
library(pharmaverseadam)
library(tern)
library(dplyr)
adsl <- adsl %>%
df_explicit_na()
```

## Start preprocessing
## Data preprocessing

Now we will add some pre-processing to create some extra formatted variables ready for display in the table.

```{r preproc}
# Create categorical variables
adsl <- adsl %>%
#| message: false
library(dplyr)
# Create categorical variables, remove screen failures, and assign column labels
adsl <- pharmaverseadam::adsl |>
filter(!ACTARM %in% "Screen Failure") |>
mutate(
SEX = factor(case_when(
SEX == "M" ~ "Male",
SEX == "F" ~ "Female",
SEX == "U" ~ "Unknown",
SEX == "UNDIFFERENTIATED" ~ "Undifferentiated"
)),
AGEGR1 = factor(
SEX = case_match(SEX, "M" ~ "MALE", "F" ~ "FEMALE"),
AGEGR1 =
case_when(
between(AGE, 18, 40) ~ "18-40",
between(AGE, 41, 64) ~ "41-64",
AGE > 64 ~ ">=65"
),
levels = c("18-40", "41-64", ">=65")
)
) |>
factor(levels = c("18-40", "41-64", ">=65"))
) |>
labelled::set_variable_labels(AGE = "Age (yr)",
AGEGR1 = "Age group",
SEX = "Sex",
RACE = "Race")
```

## {gtsummary} & {cards}

In the example below, we will use the [{gtsummary}](https://www.danieldsjoberg.com/gtsummary/) and [{cards}](https://insightsengineering.github.io/cards/) packages to create a demographics tables.

- The {cards} package creates Analysis Results Datasets (ARDs, which are a part of the [CDISC Analysis Results Standard](https://www.cdisc.org/standards/foundational/analysis-results-standard)).
- The {gtsummary} utilizes ARDs to create tables.

#### ARD ➡ Table

In the example below, we first build an ARD with the needed summary statistics using {cards}.
Then, we use the ARD to build the demographics table with {gtsummary}.

```{r gtsummary-table}
#| message: false
library(cards)
library(gtsummary)
theme_gtsummary_compact() # reduce default padding and font size for a gt table
# build the ARD with the needed summary statistics using {cards}
ard <-
ard_stack(
adsl,
ard_continuous(variables = AGE),
ard_categorical(variables = c(AGEGR1, SEX, RACE)),
.by = ACTARM, # split results by treatment arm
.attributes = TRUE # optionally include column labels in the ARD
)
# use the ARD to create a demographics table using {gtsummary}
tbl_ard_summary(
cards = ard,
by = ACTARM,
include = c(AGE, AGEGR1, SEX, RACE),
type = AGE ~ "continuous2",
statistic = AGE ~ c("{N}", "{mean} ({sd})", "{median} ({p25}, {p75})", "{min}, {max}")
) |>
bold_labels() |>
modify_header(all_stat_cols() ~ "**{level}** \nN = {n}") |> # add Ns to header
modify_footnote(everything() ~ NA) # remove default footnote
```

## Demographic table
#### Table ➡ ARD

One may also build the demographics in the classic way using `gtsummary::tbl_summary()` from a data frame, then extract the ARD from the table object.

```{r gtsummary-ard}
# build demographics table directly from a data frame
tbl <- adsl |> tbl_summary(by = ACTARM, include = c(AGE, AGEGR1, SEX, RACE))
# extract ARD from table object
gather_ard(tbl)[[1]] |> select(-gts_column) # removing column so ARD fits on page
```

## {rtables} & {tern}

The packages used with a brief description of their purpose are as follows:

* [`{rtables}`](https://insightsengineering.github.io/rtables/): designed to create and display complex tables with R.
* [`{tern}`](https://insightsengineering.github.io/tern/): contains analysis functions to create tables and graphs used for clinical trial reporting.

After installation of packages, the first step is to load our pharmaverse packages and input data. Here, we are going to encode missing entries in a data frame `adsl`.

Note that `{tern}` depends on `{rtables}` so the latter is automatically attached.

```{r rtables-setup, message=FALSE, warning=FALSE, results='hold'}
library(tern)
adsl2 <- adsl |>
df_explicit_na()
```

Now we create the demographic table.

```{r table}
```{r rtables-table}
vars <- c("AGE", "AGEGR1", "SEX", "RACE")
var_labels <- c(
"Age (yr)",
Expand All @@ -71,15 +126,15 @@ var_labels <- c(
"Race"
)
lyt <- basic_table(show_colcounts = TRUE) %>%
split_cols_by(var = "ACTARM") %>%
add_overall_col("All Patients") %>%
lyt <- basic_table(show_colcounts = TRUE) |>
split_cols_by(var = "ACTARM") |>
add_overall_col("All Patients") |>
analyze_vars(
vars = vars,
var_labels = var_labels
)
result <- build_table(lyt, adsl)
result <- build_table(lyt, adsl2)
result
```

0 comments on commit 0bd9051

Please sign in to comment.