|
| 1 | +--- |
| 2 | +title: "Pharmacokinetic" |
| 3 | +order: 3 |
| 4 | +--- |
| 5 | + |
| 6 | + |
| 7 | +```{r setup script, include=FALSE, purl=FALSE} |
| 8 | +invisible_hook_purl <- function(before, options, ...) { |
| 9 | + knitr::hook_purl(before, options, ...) |
| 10 | + NULL |
| 11 | +} |
| 12 | +knitr::knit_hooks$set(purl = invisible_hook_purl) |
| 13 | +``` |
| 14 | + |
| 15 | +## Introduction |
| 16 | + |
| 17 | +This guide will show you how pharmaverse packages, along with some from tidyverse, can be used to create pharmacokinetic (PK) tables, listings and graphs, using the `{pharmaverseadam}` `ADSL` and `ADPC` data as an input. |
| 18 | + |
| 19 | +The packages used with a brief description of their purpose are as follows: |
| 20 | + |
| 21 | +* [`{rtables}`](https://insightsengineering.github.io/rtables/): designed to create and display complex tables with R. |
| 22 | +* [`{tern}`](https://insightsengineering.github.io/tern/): contains analysis functions to create tables and graphs used for clinical trial reporting. |
| 23 | +* [`{rlistings}`](https://insightsengineering.github.io/rlistings/): contains framework for creating listings for clinical reporting. |
| 24 | + |
| 25 | +See catalog for PK TLGs here [PK TLG catalog](https://insightsengineering.github.io/tlg-catalog/stable/) |
| 26 | + |
| 27 | +## Load Data and Required pharmaverse Package |
| 28 | + |
| 29 | +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` and `adpc`. |
| 30 | + |
| 31 | +Note that `{tern}` depends on `{rtables}` so the latter is automatically attached. |
| 32 | + |
| 33 | +```{r setup, message=FALSE, warning=FALSE, results='hold'} |
| 34 | +library(pharmaverseadam) |
| 35 | +library(tern) |
| 36 | +library(dplyr) |
| 37 | +library(ggplot2) |
| 38 | +library(nestcolor) |
| 39 | +library(rlistings) |
| 40 | +
|
| 41 | +
|
| 42 | +adsl <- pharmaverseadam::adsl %>% |
| 43 | + df_explicit_na() |
| 44 | +
|
| 45 | +# Keep only treated subjects for graph |
| 46 | +adsl_f <- adsl %>% |
| 47 | + filter(SAFFL == "Y" & TRT01A != "Placebo") |
| 48 | +
|
| 49 | +adpc <- pharmaverseadam::adpc %>% |
| 50 | + df_explicit_na() |
| 51 | +
|
| 52 | +# For ADPC keep only concentration records and treated subjects |
| 53 | +# Keep only plasma records for this example |
| 54 | +adpc <- adpc %>% |
| 55 | + filter(PARAMCD != "DOSE" & TRT01A != "Placebo" & PCSPEC == "PLASMA" & ANL02FL == "Y") |
| 56 | +
|
| 57 | +# Setting up the data |
| 58 | +adpc_1 <- adpc %>% |
| 59 | + mutate( |
| 60 | + NFRLT = as.factor(NFRLT), |
| 61 | + AVALCAT1 = as.factor(AVALCAT1), |
| 62 | + NOMTPT = as.factor(paste(NFRLT, "/", PCTPT)) |
| 63 | + ) %>% |
| 64 | + select(NOMTPT, ACTARM, VISIT, AVAL, PARAM, AVALCAT1) |
| 65 | +
|
| 66 | +adpc_1$NOMTPT <- factor( |
| 67 | + adpc_1$NOMTPT, |
| 68 | + levels = levels(adpc_1$NOMTPT)[order(as.numeric(gsub(".*?([0-9\\.]+).*", "\\1", levels(adpc_1$NOMTPT))))] |
| 69 | +) |
| 70 | +
|
| 71 | +# Row structure |
| 72 | +lyt_rows <- basic_table() %>% |
| 73 | + split_rows_by( |
| 74 | + var = "ACTARM", |
| 75 | + split_fun = drop_split_levels, |
| 76 | + split_label = "Treatment Group", |
| 77 | + label_pos = "topleft" |
| 78 | + ) %>% |
| 79 | + add_rowcounts(alt_counts = TRUE) %>% |
| 80 | + split_rows_by( |
| 81 | + var = "VISIT", |
| 82 | + split_fun = drop_split_levels, |
| 83 | + split_label = "Visit", |
| 84 | + label_pos = "topleft" |
| 85 | + ) %>% |
| 86 | + split_rows_by( |
| 87 | + var = "NOMTPT", |
| 88 | + split_fun = drop_split_levels, |
| 89 | + split_label = "Nominal Time (hr) / Timepoint", |
| 90 | + label_pos = "topleft", |
| 91 | + child_labels = "hidden" |
| 92 | + ) |
| 93 | +``` |
| 94 | + |
| 95 | +## PK Table |
| 96 | + |
| 97 | +Now we create the PK table. |
| 98 | + |
| 99 | +```{r table} |
| 100 | +lyt <- lyt_rows %>% |
| 101 | + analyze_vars_in_cols( |
| 102 | + vars = c("AVAL", "AVALCAT1", rep("AVAL", 8)), |
| 103 | + .stats = c("n", "n_blq", "mean", "sd", "cv", "geom_mean", "geom_cv", "median", "min", "max"), |
| 104 | + .formats = c( |
| 105 | + n = "xx.", n_blq = "xx.", mean = format_sigfig(3), sd = format_sigfig(3), cv = "xx.x", median = format_sigfig(3), |
| 106 | + geom_mean = format_sigfig(3), geom_cv = "xx.x", min = format_sigfig(3), max = format_sigfig(3) |
| 107 | + ), |
| 108 | + .labels = c( |
| 109 | + n = "n", n_blq = "Number\nof\nLTRs/BLQs", mean = "Mean", sd = "SD", cv = "CV (%) Mean", |
| 110 | + geom_mean = "Geometric Mean", geom_cv = "CV % Geometric Mean", median = "Median", min = "Minimum", max = "Maximum" |
| 111 | + ), |
| 112 | + na_str = "NE", |
| 113 | + .aligns = "decimal" |
| 114 | + ) |
| 115 | +
|
| 116 | +result <- build_table(lyt, df = adpc_1, alt_counts_df = adsl) %>% prune_table() |
| 117 | +
|
| 118 | +# Decorating |
| 119 | +main_title(result) <- "Summary of PK Concentrations by Nominal Time and Treatment: PK Evaluable" |
| 120 | +subtitles(result) <- c( |
| 121 | + "Protocol: xxxxx", |
| 122 | + paste("Analyte: ", unique(adpc_1$PARAM)), |
| 123 | + paste("Treatment:", unique(adpc_1$ACTARM)) |
| 124 | +) |
| 125 | +main_footer(result) <- "NE: Not Estimable" |
| 126 | +
|
| 127 | +result |
| 128 | +``` |
| 129 | + |
| 130 | + |
| 131 | +## PK Graph |
| 132 | + |
| 133 | +Now we create the PK graph. |
| 134 | + |
| 135 | +```{r graph} |
| 136 | +use_title <- "Plot of Mean (+/- SD) Plasma Concentrations Over Time by Treatment, \nPK Evaluable Patients" |
| 137 | +use_subtitle <- "Analyte:" |
| 138 | +use_footnote <- "Program: \nOutput:" |
| 139 | +
|
| 140 | +result <- g_lineplot( |
| 141 | + df = adpc, |
| 142 | + variables = control_lineplot_vars( |
| 143 | + x = "NFRLT", |
| 144 | + y = "AVAL", |
| 145 | + group_var = "ARM", |
| 146 | + paramcd = "PARAM", |
| 147 | + y_unit = "AVALU", |
| 148 | + subject_var = "USUBJID" |
| 149 | + ), |
| 150 | + alt_counts_df = adsl_f, |
| 151 | + position = ggplot2::position_dodge2(width = 0.5), |
| 152 | + y_lab = "Concentration", |
| 153 | + y_lab_add_paramcd = FALSE, |
| 154 | + y_lab_add_unit = TRUE, |
| 155 | + interval = "mean_sdi", |
| 156 | + whiskers = c("mean_sdi_lwr", "mean_sdi_upr"), |
| 157 | + title = use_title, |
| 158 | + subtitle = use_subtitle, |
| 159 | + caption = use_footnote, |
| 160 | + ggtheme = theme_nest() |
| 161 | +) |
| 162 | +
|
| 163 | +plot <- result + theme(plot.caption = element_text(hjust = 0)) |
| 164 | +plot |
| 165 | +``` |
| 166 | + |
| 167 | +## PK Listing |
| 168 | + |
| 169 | +Now we create an example PK listing. |
| 170 | + |
| 171 | +```{r listing} |
| 172 | +analyte <- unique(adpc$PARAM) |
| 173 | +
|
| 174 | +out <- adpc %>% |
| 175 | + select(ARM, USUBJID, VISIT, NFRLT, AFRLT, AVALCAT1) |
| 176 | +
|
| 177 | +
|
| 178 | +var_labels(out) <- c( |
| 179 | + ARM = "Treatment Group", |
| 180 | + USUBJID = "Subject ID", |
| 181 | + VISIT = "Visit", |
| 182 | + NFRLT = paste0("Nominal\nSampling\nTime (", adpc$RRLTU[1], ")"), |
| 183 | + AFRLT = paste0("Actual Time\nFrom First\nDose (", adpc$RRLTU[1], ")"), |
| 184 | + AVALCAT1 = paste0("Concentration\n(", adpc$AVALU[1], ")") |
| 185 | +) |
| 186 | +
|
| 187 | +lsting <- as_listing( |
| 188 | + out, |
| 189 | + key_cols = c("ARM", "USUBJID", "VISIT"), |
| 190 | + disp_cols = names(out), |
| 191 | + default_formatting = list( |
| 192 | + all = fmt_config(align = "left"), |
| 193 | + numeric = fmt_config( |
| 194 | + format = "xx.xx", |
| 195 | + na_str = " ", |
| 196 | + align = "right" |
| 197 | + ) |
| 198 | + ), |
| 199 | + main_title = paste( |
| 200 | + "Listing of", |
| 201 | + analyte, |
| 202 | + "Concentration by Treatment Group, Subject and Nominal Time, PK Population\nProtocol: xxnnnnn" |
| 203 | + ), |
| 204 | + subtitles = paste("Analyte:", analyte) |
| 205 | +) |
| 206 | +
|
| 207 | +head(lsting, 28) |
| 208 | +``` |
| 209 | + |
| 210 | + |
| 211 | + |
0 commit comments