Skip to content

Commit 1615a4b

Browse files
authored
Merge branch 'main' into 105_table_09_tplyr
2 parents 9f181f8 + 90eca39 commit 1615a4b

21 files changed

+1451
-34
lines changed

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export(alt_counts_df_preproc)
44
export(basic_table_annot)
55
export(make_fig_01)
66
export(make_fig_02)
7+
export(make_fig_14)
78
export(make_table_02)
89
export(make_table_02_gtsum)
910
export(make_table_02_tplyr)

NEWS.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
`make_table_06`, `make_table_07`, `make_table_08`, `make_table_09`, `make_table_10`, `make_table_11`, `make_table_12`,
66
`make_table_13`, `make_table_14`, `make_table_15`, `make_table_16`, `make_table_17`, `make_table_18`, `make_table_20`,
77
`make_table_21`, `make_table_22`, `make_table_32`, `make_table_33`, `make_table_34`, `make_table_35`.
8-
* Added new functions for creating standard FDA figures: `make_fig_01`, `make_fig_02`.
8+
* Added new functions for creating standard FDA figures: `make_fig_01`, `make_fig_02`, `make_fig_14`.
99
* Added helper functions used within table functions:
1010
* `basic_table_annot` for adding basic table annotations (titles, footnotes, column counts).
1111
* `split_cols_by_arm` for splitting columns by arm with option to add total column.

R/argument_convention.R

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
#' @param xticks (`vector` of `numeric`)\cr x-axis tick positions. If `NA` (default), tick mark positions are
7373
#' automatically calculated.
7474
#' @param x_lab (`character`)\cr x-axis label.
75+
#' @param yticks (`vector` of `numeric`)\cr y-axis tick positions. If `NA` (default), tick mark positions are
76+
#' automatically calculated.
7577
#' @param y_lab (`character`)\cr y-axis label.
7678
#'
7779
#' @name argument_convention

R/fda-fig_14.R

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#' FDA Figure 14: Mean and 95% Confidence Interval of Systolic Blood Pressure Over Time
2+
#' by Treatment Arm, Safety Population, Trial X
3+
#'
4+
#' @details
5+
#' * `df` must contain the variables `AVAL` and `PARAMCD`, and the variables specified by `arm_var`,
6+
#' `saffl_var`, `visit_var`, and `add_cond`.
7+
#' * Flag variables (i.e. `XXXFL`) are expected to have two levels: `"Y"` (true) and `"N"` (false). Missing values in
8+
#' flag variables are treated as `"N"`.
9+
#' * It is assumed that `df` contains one unique record per patient.
10+
#'
11+
#' @inheritParams argument_convention
12+
#' @param add_table (`flag`)\cr whether "Mean Value" and "Number of Patients" tables should be printed under the plot
13+
#' @param visit_var (`character`)\cr visit variable to put on the x-axis
14+
#' @param paramcd_val (`character`)\cr value of `PARAMCD` to plot
15+
#' @param add_cond (`expr`)\cr expression that provides additional filters for the analysis
16+
#' (for instance on `ATPT` or `VSPOS`)
17+
#' @param annotations (named `list` of `character`)\cr list of annotations to add to the figure. Valid annotation types
18+
#' are `title`, `subtitles`, and `caption`. Each name-value pair should use the annotation type as name and the
19+
#' desired string as value.
20+
#'
21+
#' @return A `ggplot2` object.
22+
#'
23+
#' @examples
24+
#' advs <- random.cdisc.data::cadvs
25+
#'
26+
#' fig <- make_fig_14(
27+
#' df = advs,
28+
#' add_cond = bquote("ONTRTFL == 'Y' | ABLFL == 'Y'"),
29+
#' add_table = TRUE,
30+
#' yticks = c(135, 140, 145, 150, 155, 160)
31+
#' )
32+
#' fig
33+
#'
34+
#' @export
35+
make_fig_14 <- function(df,
36+
arm_var = "ARM",
37+
saffl_var = "SAFFL",
38+
visit_var = "AVISIT",
39+
paramcd_val = "SYSBP",
40+
add_cond = NULL,
41+
x_lab = "",
42+
y_lab = NULL,
43+
yticks = NA,
44+
ggtheme = NULL,
45+
add_table = TRUE,
46+
annotations = NULL) {
47+
checkmate::assert_subset(c(arm_var, saffl_var, visit_var), names(df))
48+
assert_flag_variables(df, saffl_var)
49+
50+
df <- df %>%
51+
as_tibble() %>%
52+
filter(
53+
.data[[saffl_var]] == "Y",
54+
PARAMCD == {{ paramcd_val }},
55+
!is.na(AVAL)
56+
) %>%
57+
df_explicit_na()
58+
59+
if (!(is.null({{ add_cond }}))) {
60+
df <- df %>%
61+
filter(!!rlang::parse_expr(add_cond))
62+
}
63+
64+
if (is.null({{ y_lab }})) {
65+
y_param <- unique(df$PARAM)
66+
y_avalu <- unique(df$AVALU)
67+
68+
y_lab <- paste0("Mean Value (95% CI)", "\n", y_param, " (", y_avalu, ")")
69+
}
70+
71+
df <- df %>%
72+
group_by(!!sym(arm_var), !!sym(visit_var), .drop = TRUE) %>%
73+
summarise(
74+
mean = mean(AVAL, na.rm = TRUE),
75+
sd = sd(AVAL, na.rm = TRUE),
76+
n = n()
77+
) %>%
78+
mutate(
79+
se = sd / sqrt(n),
80+
lower_ci = mean - qt(1 - (0.05 / 2), n - 1) * se,
81+
upper_ci = mean + qt(1 - (0.05 / 2), n - 1) * se
82+
) %>%
83+
ungroup()
84+
85+
g <-
86+
ggplot(
87+
data = df,
88+
aes(
89+
x = !!sym(visit_var),
90+
y = mean,
91+
group = .data[[arm_var]],
92+
color = .data[[arm_var]]
93+
)
94+
) +
95+
geom_point(position = position_dodge(width = 0.5)) +
96+
geom_line(position = position_dodge(width = 0.5)) +
97+
geom_errorbar(
98+
aes(
99+
ymin = lower_ci,
100+
ymax = upper_ci
101+
),
102+
position = position_dodge(width = 0.5)
103+
) +
104+
labs(
105+
title = annotations[["title"]],
106+
subtitle = annotations[["subtitle"]],
107+
caption = annotations[["caption"]],
108+
x = x_lab,
109+
y = y_lab
110+
) +
111+
theme(
112+
legend.position = "bottom",
113+
legend.title = element_blank(),
114+
plot.margin = unit(c(0.05, 0.05, 0, 0.025), "npc")
115+
)
116+
117+
if (any(!is.na(yticks))) {
118+
g <- g +
119+
scale_y_continuous(breaks = yticks, limits = c(min(yticks), max(yticks)))
120+
}
121+
122+
if (!is.null(ggtheme)) g <- g + ggtheme
123+
124+
if (add_table) {
125+
g_legend <- cowplot::get_legend(g)
126+
g <- g + theme(legend.position = "none")
127+
128+
tbl_n <- df %>%
129+
mutate(meanr = sprintf("%.1f", mean)) %>%
130+
arrange(desc(!!sym(arm_var)))
131+
132+
g_tbl1 <- ggplot(tbl_n, aes(x = !!sym(visit_var), y = !!sym(arm_var))) +
133+
theme(
134+
axis.title.x = element_blank(),
135+
axis.title.y = element_blank(),
136+
axis.ticks.x = element_blank(),
137+
axis.ticks.y = element_blank(),
138+
panel.background = element_blank(),
139+
axis.text.x = element_blank(),
140+
panel.border = element_rect(color = "black", fill = NA, linewidth = 0.5),
141+
plot.margin = unit(c(0.1, 0.05, 0, 0.025), "npc"),
142+
plot.title = element_text(size = 10)
143+
) +
144+
labs(title = "Mean Value")
145+
146+
for (i in seq_len(nrow(tbl_n))) {
147+
g_tbl1 <- g_tbl1 +
148+
annotate("text", label = as.character(tbl_n$meanr[i]), x = tbl_n[[visit_var]][i], y = tbl_n[[arm_var]][i])
149+
}
150+
151+
g_tbl2 <- ggplot(tbl_n, aes(x = !!sym(visit_var), y = !!sym(arm_var))) +
152+
theme(
153+
axis.title.x = element_blank(),
154+
axis.title.y = element_blank(),
155+
axis.ticks.x = element_blank(),
156+
axis.ticks.y = element_blank(),
157+
panel.background = element_blank(),
158+
axis.text.x = element_blank(),
159+
panel.border = element_rect(color = "black", fill = NA, linewidth = 0.2),
160+
plot.margin = unit(c(0.1, 0.05, 0, 0.025), "npc"),
161+
plot.title = element_text(size = 10)
162+
) +
163+
labs(title = "Number of Patients with Data")
164+
165+
for (i in seq_len(nrow(tbl_n))) {
166+
g_tbl2 <- g_tbl2 +
167+
annotate("text", label = as.character(tbl_n$n[i]), x = tbl_n[[visit_var]][i], y = tbl_n[[arm_var]][i])
168+
}
169+
170+
cowplot::plot_grid(
171+
g,
172+
g_tbl1,
173+
g_tbl2,
174+
g_legend,
175+
align = "v",
176+
axis = "l",
177+
ncol = 1,
178+
rel_heights = c(0.60, 0.15, 0.15, 0.1)
179+
)
180+
} else {
181+
g
182+
}
183+
}

R/fda-table_22.R

+1-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@
2525
#' AGE >= 65 & AGE < 75 ~ ">=65 to <75",
2626
#' AGE >= 75 ~ ">=75"
2727
#' )) %>% formatters::with_label("Age Group, years")) %>%
28-
#' formatters::var_relabel(
29-
#' AGE = "Age, years"
30-
#' )
28+
#' formatters::var_relabel(AGE = "Age, years")
3129
#'
3230
#' adae <- random.cdisc.data::cadae
3331
#'

_quarto.yml

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ website:
105105
- quarto/table-templates/template-table_35.qmd
106106
- quarto/figure-templates/template-fig_01.qmd
107107
- quarto/figure-templates/template-fig_02.qmd
108+
- quarto/figure-templates/template-fig_14.qmd
108109
- text: About
109110
file: quarto/about.qmd
110111
- text: Resources

man/argument_convention.Rd

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/make_fig_14.Rd

+79
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/make_table_22.Rd

+1-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
169 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
title: FDA Figure 14
3+
subtitle: Mean and 95% Confidence Interval of Systolic Blood Pressure Over Time by Treatment Arm, Safety Population, Trial X
4+
format: html
5+
---
6+
7+
::: panel-tabset
8+
## Spec. Screenshot
9+
10+
![](../assets/images/screenshots/fig_14.png){fig-align="center"}
11+
12+
## ggplot2 Figure
13+
14+
```{r fig, message=FALSE, warning=FALSE, fig.height=7, fig.width=9}
15+
# Load Libraries & Data
16+
library(falcon)
17+
18+
advs <- random.cdisc.data::cadvs
19+
20+
make_fig_14(
21+
df = advs,
22+
add_cond = bquote("ONTRTFL == 'Y' | ABLFL == 'Y'"),
23+
add_table = TRUE,
24+
yticks = c(135, 140, 145, 150, 155, 160)
25+
)
26+
```
27+
28+
## Figure Setup
29+
30+
```{r fig, eval=FALSE, echo=TRUE}
31+
```
32+
33+
## Function Details
34+
35+
### `make_fig_14()`
36+
37+
------------------------------------------------------------------------
38+
39+
Required variables:
40+
41+
- **`df`**: The variables `AVAL` and `PARAMCD`, and the variables specified by `arm_var`, `saffl_var`, and `visit_var`.
42+
43+
| Argument | Description | Default |
44+
|:--------------|:------------------------------------------|:--------------|
45+
| `df` | (`data.frame`) Dataset (typically ADVS) required to build table. | *No default* |
46+
| `arm_var` | (`character`) Arm variable used to split table into columns. | `"ARM"` |
47+
| `saffl_var` | (`character`) Flag variable used to indicate inclusion in safety population. | `"SAFFL"` |
48+
| `visit_var` | (`character`) Visit variable to put on the x-axis. | `"AVISIT"` |
49+
| `paramcd_val` | (`character`) Value of `PARAMCD` to plot. | `"SYSBP"` |
50+
| `add_cond` | (`expression`) Additional filter for the analysis (e.g on ATPT or VSPOS). | `NULL` |
51+
| `x_lab` | (`character`) x-axis label. | `paste0("Time from first dose (", u_trtdur, ")")` |
52+
| `y_lab` | (`character`) y-axis label. | `"Percent of Patients (%)"` |
53+
| `yticks` | (`vector` of `numeric`) y-axis tick positions. If `NA` (default), tick mark positions are automatically calculated. | `NA` |
54+
| `ggtheme` | (`function`) Function from `ggplot2` to apply over the plot. | `NULL` |
55+
| `add_table` | (`flag`) whether "Number of Patients" table should be printed under the plot. | `TRUE` |
56+
| `annotations` | (named `list` of `character`) List of annotations to add to the table. Valid annotation types are `title`, `subtitles`, and `caption`. Each name-value pair should use the annotation type as name and the desired string as value. | `NULL` |
57+
58+
Source code for this function is available [here](https://github.com/pharmaverse/falcon/blob/main/R/fda-fig_14.R).
59+
:::

quarto/index-templates.qmd

+3
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,8 @@ title: Template Library Index
5858

5959
### **FDA Figures**
6060
- [FDA Figure 1 -- Time to Permanent Discontinuation of Study Drug, Safety Population, Pooled Analyses](figure-templates/template-fig_01.qmd)
61+
6162
- [FDA Figure 2 -- Time to Last Follow Up, Safety Population, Pooled Analyses](figure-templates/template-fig_02.qmd)
6263

64+
- [FDA Figure 14 -- Mean and 95% Confidence Interval of Systolic Blood Pressure Over Time by Treatment Arm, Safety Population, Trial X](figure-templates/template-fig_14.qmd)
65+

0 commit comments

Comments
 (0)