1
1
# ' FDA Table 2: Baseline Demographic and Clinical Characteristics, Safety Population, Pooled Analyses
2
2
# '
3
3
# ' @details
4
- # ' * `data` must contain the variables specified by `continuous_vars`, and `categorical_vars`.
5
- # ' * `tbl_engine` must be one of `gtsummary`, `rtables`, `tplyr`.
4
+ # ' * `data` must contain the variables specified by `vars`.
6
5
# ' * `return_ard` set to `TRUE` or `FALSE`; whether the intermediate ARD object should be returned.
7
6
# '
8
7
# ' @inheritParams argument_convention
13
12
# ' @describeIn make_table_02 Create FDA table 2 using an ARD.
14
13
# '
15
14
# ' @return
16
- # ' * `make_table_02` returns an object matching the selected `tbl_engine` argument .
15
+ # ' * `make_table_02` returns a list containing a gtsummary table object .
17
16
# ' The intermediary `ARD` object can also be returned with `return_ard` set to `TRUE`.
18
17
# '
19
18
# ' @examples
@@ -25,300 +24,35 @@ NULL
25
24
# ' AGE >= 65 ~ ">=65",
26
25
# ' AGE >= 65 & AGE < 75 ~ ">=65 to <75",
27
26
# ' AGE >= 75 ~ ">=75"
28
- # ' ))
27
+ # ' )))
29
28
# '
30
29
# ' tbl <- make_table_02(data = adsl)
31
30
# ' tbl
32
31
# '
33
32
# ' @export
34
33
35
34
make_table_02 <- function (data ,
35
+ show_colcounts = TRUE ,
36
+ arm_var = " ARM" ,
37
+ saffl_var = " SAFFL" ,
38
+ vars = c(" SEX" , " AGE" , " AGEGR1" , " RACE" , " ETHNIC" , " COUNTRY" ),
39
+ lbl_vars = formatters :: var_labels(data , fill = TRUE )[vars ],
40
+ lbl_overall = " Total Population" ,
41
+ na_rm = FALSE ,
36
42
... ,
37
- tbl_engine = " gtsummary" ,
38
43
return_ard = TRUE ) {
39
44
# check data viability
40
- assert_subset(continuous_vars , names(data ))
41
- assert_subset( categorical_vars , names( data ) )
45
+ checkmate :: assert_subset(c( vars , arm_var , saffl_var ) , names(data ))
46
+ assert_flag_variables( data , saffl_var )
42
47
43
- if (tbl_engine == " rtables" ) {
44
- ard <- " ARD not available for {rtables}"
45
- tbl <- make_table_02_rtables(df = data )
46
- } else {
47
- ard <- make_ard_02(... )
48
- # commenting out this table building portion until package refactor
49
- # if (tbl_engine == "gtsummary") {
50
- # tbl <- make_table_02_gtsum(ard, ...)
51
- # } else {
52
- # tbl <- make_table_02_tplyr(ard, ...)
53
- # }
54
- }
55
-
56
- if (return_ard ) {
57
- res <- list (ard = ard )
58
- } else {
59
- res <- tbl
60
- }
61
- }
62
-
63
- # ' @keywords Internal
64
- make_ard_02 <- function (data = data ,
65
- by = " ARM" ,
66
- continuous_vars = c(" AGE" ),
67
- categorical_vars = c(" SEX" , " AGEGR1" , " RACE" , " ETHNIC" )) {
68
- ard <- cards :: ard_stack(
69
- data = data ,
70
- by = by ,
71
- cards :: ard_continuous(
72
- variables = continuous_vars ,
73
- statistic = ~ continuous_summary_fns(c(" mean" , " sd" , " median" , " min" , " max" ))
74
- ),
75
- cards :: ard_categorical(variables = categorical_vars )
76
- )
77
-
78
- return (ard )
79
- }
80
-
81
-
82
- # ' @keywords Internal
83
- make_table_02_rtables <- function (df ,
84
- alt_counts_df = NULL ,
85
- show_colcounts = TRUE ,
86
- arm_var = " ARM" ,
87
- saffl_var = " SAFFL" ,
88
- vars = c(" SEX" , " AGE" , " AGEGR1" , " RACE" , " ETHNIC" , " COUNTRY" ),
89
- lbl_vars = formatters :: var_labels(df , fill = TRUE )[vars ],
90
- lbl_overall = " Total Population" ,
91
- na_rm = FALSE ,
92
- prune_0 = TRUE ,
93
- annotations = NULL ) {
94
- assert_subset(c(vars , arm_var , saffl_var ), names(df ))
95
- assert_flag_variables(df , saffl_var )
96
-
97
- df <- df %> %
98
- filter(.data [[saffl_var ]] == " Y" ) %> %
99
- df_explicit_na()
100
-
101
- alt_counts_df <- alt_counts_df_preproc(alt_counts_df , id_var , arm_var , saffl_var )
102
-
103
- lyt <- basic_table_annot(show_colcounts , annotations ) %> %
104
- split_cols_by_arm(arm_var , lbl_overall ) %> %
105
- analyze_vars(
106
- vars = vars ,
107
- var_labels = lbl_vars ,
108
- show_labels = " visible" ,
109
- .stats = c(" mean_sd" , " median_range" , " count_fraction" ),
110
- .formats = NULL ,
111
- na.rm = na_rm
112
- ) %> %
113
- append_topleft(" Characteristic" )
114
-
115
- tbl <- build_table(lyt , df = df , alt_counts_df = alt_counts_df )
116
- if (prune_0 ) tbl <- prune_table(tbl )
117
-
118
- tbl
119
- }
120
-
121
- # ' @describeIn make_table_02 Create FDA table 2 using functions from `Tplyr` and `tfrmt`.
122
- # '
123
- # ' @param tplyr_raw (`flag`)\cr whether the raw `tibble` created using `Tplyr` functions should be returned, or the
124
- # ' table formatted using functions from `tfrmt` should be returned (default).
125
- # '
126
- # ' @note
127
- # ' * `make_table_02_tplyr` does not currently support footnote annotations
128
- # ' * `make_table_02_tplyr` does not currently support `alt_counts_df` when `tplyr_raw = TRUE`.
129
- # '
130
- # ' @return
131
- # ' * `make_table_02_tplyr` returns a `gt_tbl` object when `tplyr_raw = FALSE` (default) and
132
- # ' a `tibble` object when `tplyr_raw = TRUE`.
133
- # '
134
- # ' @examples
135
- # ' tbl <- make_table_02_tplyr(df = adsl)
136
- # ' tbl
137
- # '
138
- # ' @keywords Internal
139
- make_table_02_tplyr <- function (df ,
140
- alt_counts_df = NULL ,
141
- show_colcounts = TRUE ,
142
- arm_var = " ARM" ,
143
- saffl_var = " SAFFL" ,
144
- vars = c(" SEX" , " AGE" , " AGEGR1" , " RACE" , " ETHNIC" , " COUNTRY" ),
145
- lbl_vars = formatters :: var_labels(df , fill = TRUE )[vars ],
146
- lbl_overall = " Total Population" ,
147
- na_rm = FALSE ,
148
- prune_0 = TRUE ,
149
- annotations = NULL ,
150
- tplyr_raw = FALSE ) {
151
- assert_subset(c(saffl_var , vars , arm_var ), names(df ))
152
- assert_flag_variables(df , saffl_var )
153
-
154
- df <- df %> % df_explicit_na()
155
- for (lbl in lbl_vars ) {
156
- df [[lbl ]] <- lbl
157
- }
158
-
159
- var_types <- lapply(df [vars ], function (x ) if (is.numeric(x )) " numeric" else " count" )
160
-
161
- lyt <- tplyr_table(df , treat_var = !! sym(arm_var ), where = !! sym(saffl_var ) == " Y" )
162
-
163
- if (! is.null(lbl_overall )) lyt <- lyt %> % add_total_group(group_name = lbl_overall )
164
-
165
- for (i in seq_along(vars )) {
166
- var <- vars [i ]
167
- var_lbl <- lbl_vars [i ]
168
- if (var_types [[var ]] == " numeric" ) {
169
- if (tplyr_raw ) {
170
- lyt <- lyt %> % add_layer(
171
- group_desc(vars(!! sym(var )), by = !! sym(var_lbl )) %> %
172
- set_format_strings(
173
- " Mean (SD)" = f_str(" xx.x (xx.x)" , mean , sd ),
174
- " Median (Min - Max)" = f_str(" xx.x (xx.x - xx.x)" , median , min , max )
175
- )
176
- )
177
- } else {
178
- lyt <- lyt %> % add_layer(
179
- group_desc(vars(!! sym(var )), by = !! sym(var_lbl )) %> %
180
- set_format_strings(
181
- " Mean" = f_str(" xx.xxxx" , mean ), " SD" = f_str(" xx.xxxx" , sd ), " Median" = f_str(" xx.xxxx" , median ),
182
- " Min" = f_str(" xx.xxxx" , min ), " Max" = f_str(" xx.xxxx" , max )
183
- )
184
- )
185
- }
186
- } else {
187
- if (tplyr_raw ) {
188
- lyt <- lyt %> % add_layer(
189
- group_count(vars(!! sym(var )), by = !! sym(var_lbl )) %> %
190
- set_format_strings(f_str(" xx (xx.x%)" , n , pct ))
191
- )
192
- } else {
193
- lyt <- lyt %> % add_layer(
194
- group_count(vars(!! sym(var )), by = !! sym(var_lbl )) %> %
195
- set_format_strings(f_str(" xx;xx.xxxx" , n , pct ))
196
- )
197
- }
198
- }
199
- }
200
- tbl <- lyt %> % build()
201
-
202
- if (na_rm ) {
203
- na_ind <- tbl [, 2 ] != " <Missing>"
204
- tbl <- tbl [na_ind , ]
205
- }
206
-
207
- if (tplyr_raw ) {
208
- tbl <- tbl %> %
209
- arrange(ord_layer_index , ord_layer_1 , ord_layer_2 ) %> %
210
- apply_row_masks(row_breaks = TRUE ) %> %
211
- select(starts_with(" row_label" ), starts_with(" var1_" )) %> %
212
- add_column_headers(
213
- paste0(
214
- " Characteristic | | " ,
215
- paste0(
216
- levels(df [[arm_var ]]), if (show_colcounts ) paste0(" \n (N=**" , levels(df [[arm_var ]]), " **)| " ) else " | " ,
217
- collapse = " "
218
- ),
219
- ifelse(! is.null(lbl_overall ), paste0(lbl_overall , ifelse(show_colcounts , c(" \n (N=**Total**)" ), " " ), " " ))
220
- ),
221
- header_n = header_n(lyt )
222
- )
223
-
224
- if (prune_0 ) {
225
- prune_ind <- apply(tbl , MARGIN = 1 , function (x ) all(x == " " ) || ! all(gsub(" [0()\\ % ]" , " " , x [- c(1 : 2 )]) == " " ))
226
- tbl <- tbl [prune_ind , ]
227
- }
228
- } else {
229
- tbl <- tbl %> %
230
- tidyr :: pivot_longer(head(names(. )[- c(1 : 2 )], - 3 ), names_to = " column" , values_to = " value" ) %> %
231
- mutate(
232
- tbl_lbl = " Characteristic" ,
233
- column = gsub(" var1_" , " " , column ),
234
- param = ifelse(row_label2 %in% c(" Mean" , " SD" , " Median" , " Min" , " Max" ), row_label2 , " n;pct" ),
235
- row_label2 = case_when(
236
- row_label2 %in% c(" Mean" , " SD" ) ~ " Mean (SD)" ,
237
- row_label2 %in% c(" Median" , " Min" , " Max" ) ~ " Median (Min - Max)" ,
238
- .default = row_label2
239
- )
240
- ) %> %
241
- tidyr :: separate_rows(c(" param" , " value" ), sep = " ;" ) %> %
242
- mutate(value = as.numeric(value ))
243
-
244
- if (show_colcounts ) {
245
- colcounts <- summary(if (! is.null(alt_counts_df )) alt_counts_df [[arm_var ]] else df [[arm_var ]])
246
- big_ns <- tibble(
247
- column = c(levels(df [[arm_var ]]), lbl_overall ),
248
- param = " bigN" ,
249
- value = if (! is.null(lbl_overall )) c(colcounts , sum(colcounts )) else colcounts ,
250
- )
251
- tbl <- bind_rows(tbl , big_ns )
252
- }
253
-
254
- if (prune_0 ) {
255
- tbl <- tbl %> %
256
- group_by(ord_layer_index , ord_layer_2 ) %> %
257
- filter(sum(value ) > 0 ) %> %
258
- ungroup()
259
- }
260
- big_n_tbl <- if (show_colcounts ) big_n_structure(param_val = " bigN" , n_frmt = frmt(" \n (N=xx)" )) else NULL
261
-
262
- tbl <- tfrmt(
263
- group = c(tbl_lbl , row_label1 ),
264
- label = row_label2 ,
265
- column = column ,
266
- param = param ,
267
- value = value ,
268
- title = annotations [[" title" ]],
269
- subtitle = paste(annotations [[" subtitles" ]], collapse = " , " ),
270
- sorting_cols = c(ord_layer_1 , ord_layer_2 ),
271
- body_plan = body_plan(
272
- frmt_structure(
273
- group_val = " .default" , label_val = " .default" ,
274
- frmt_combine(" {n} {pct}" , n = frmt(" xx" ), pct = frmt_when(" ==0" ~ " " , TRUE ~ frmt(" (xx.x%)" )))
275
- ),
276
- frmt_structure(
277
- group_val = " .default" , label_val = " Mean (SD)" ,
278
- frmt_combine(" {Mean} ({SD})" , Mean = frmt(" xx.x" ), SD = frmt(" xx.x" ))
279
- ),
280
- frmt_structure(
281
- group_val = " .default" , label_val = " Median (Min - Max)" ,
282
- frmt_combine(" {Median} ({Min} - {Max})" , Median = frmt(" xx.x" ), Min = frmt(" xx.x" ), Max = frmt(" xx.x" ))
283
- )
284
- ),
285
- col_plan = col_plan(- starts_with(" ord" )),
286
- big_n = big_n_tbl
287
- ) %> %
288
- print_to_gt(tbl )
289
- }
290
- tbl
291
- }
292
-
293
- # ' @describeIn make_table_02 Create FDA table 2 using functions from `gtsummary`.
294
- # '
295
- # ' @return
296
- # ' * `make_table_02_gtsum` returns a `tbl_summary` object.
297
- # '
298
- # ' @examples
299
- # ' tbl <- make_table_02_gtsum(df = adsl)
300
- # ' tbl
301
- # '
302
- # ' @keywords Internal
303
- make_table_02_gtsum <- function (df ,
304
- show_colcounts = TRUE ,
305
- arm_var = " ARM" ,
306
- saffl_var = " SAFFL" ,
307
- vars = c(" SEX" , " AGE" , " AGEGR1" , " RACE" , " ETHNIC" , " COUNTRY" ),
308
- lbl_vars = formatters :: var_labels(df , fill = TRUE )[vars ],
309
- lbl_overall = " Total Population" ,
310
- na_rm = FALSE ) {
311
- assert_subset(c(vars , arm_var , saffl_var ), names(df ))
312
- assert_flag_variables(df , saffl_var )
313
-
314
- df <- df %> %
48
+ df <- data %> %
315
49
filter(.data [[saffl_var ]] == " Y" ) %> %
316
50
select(all_of(c(vars , arm_var )))
317
51
318
52
if (! na_rm ) df <- df %> % df_explicit_na()
319
53
320
54
tbl <- df %> %
321
- tbl_summary(
55
+ gtsummary :: tbl_summary(
322
56
by = arm_var ,
323
57
type = all_continuous() ~ " continuous2" ,
324
58
statistic = list (
@@ -333,16 +67,16 @@ make_table_02_gtsum <- function(df,
333
67
label = as.list(lbl_vars ) %> % setNames(vars )
334
68
) %> %
335
69
gtsummary :: bold_labels() %> %
336
- modify_header(all_stat_cols() ~ " **{level}** \n N = {n}" ) %> %
337
- add_overall(last = TRUE , col_label = paste0(" **" , lbl_overall , " ** \n N = {n}" )) %> %
70
+ gtsummary :: modify_header(all_stat_cols() ~ " **{level}** \n N = {n}" ) %> %
71
+ gtsummary :: add_overall(last = TRUE , col_label = paste0(" **" , lbl_overall , " ** \n N = {n}" )) %> %
338
72
gtsummary :: add_stat_label(label = all_continuous2() ~ c(" Mean (SD)" , " Median (min - max)" )) %> %
339
- modify_footnote(update = everything() ~ NA ) %> %
73
+ gtsummary :: modify_footnote(update = everything() ~ NA ) %> %
340
74
gtsummary :: modify_column_alignment(columns = all_stat_cols(), align = " right" )
341
75
342
- gtsummary :: with_gtsummary_theme(
343
- x = gtsummary :: theme_gtsummary_compact(),
344
- expr = as_gt(tbl )
345
- )
76
+ if (return_ard ) {
77
+ ard <- gtsummary :: gather_ard(tbl )
78
+ res <- list (tbl = tbl , ard = ard )
79
+ } else {
80
+ res <- list (tbl = tbl )
81
+ }
346
82
}
347
-
348
-
0 commit comments