Add an empty row at the end of each split_rows_by() section
Add an empty row at the end of each split_rows_by() section
Firstly, thanks for the great package, which is a valuable asset for the community!
I would like to have an empty row in btw split_rows_by() sections, and I have a work-around example below, as showed in cfun_lvl2(). Are there more elegant solutions in {rtables}? I wonder if it's reasonable to consider opening a new argument in split_rows_by(), such as something like add_empty_row flag, or there is a more appropriate place for such customization?
Thanks, Freeman
library(dplyr)
library(rtables)
cfun_lvl1 <- function(df, labelstr, .N_col, .spl_context){
n <- df %>% dplyr::select(USUBJID) %>% dplyr::n_distinct()
ret <- in_rows(.names = labelstr,
rcell(c(n, n/.N_col*100), formatters::sprintf_format("%.0f (%.1f)"))
)
return(ret)
}
cfun_lvl2 <- function(df, labelstr, .N_col, .spl_context){
n <- df %>% dplyr::select(USUBJID) %>% dplyr::n_distinct()
cust_value <- c(n, n/.N_col*100)
cust_format <- formatters::sprintf_format("%.0f (%.1f)")
## a temp work-around for adding empty row at the end of 2nd-level category value within
## 1st-level category.
curr_lvl2_val <- .spl_context$value[[nrow(.spl_context)]]
last_lvl2_val <- .spl_context$full_parent_df[[nrow(.spl_context)]][[.spl_context$split[2]]] %>% levels %>% tail(1)
if ( curr_lvl2_val == last_lvl2_val ) {
ret <- in_rows(.names = c(labelstr, " "),
.list = list(c(n, n/.N_col*100), NULL),
.formats = c(cust_format, "xx")
)
} else {
rc <- rcell(cust_value, format = cust_format)
ret <- in_rows(.names = labelstr, rc)
}
return(ret)
}
tbl_recipe <- basic_table() %>%
split_cols_by("ARM") %>%
split_rows_by("COUNTRY", split_fun = drop_split_levels) %>%
summarize_row_groups(cfun = cfun_lvl1) %>%
split_rows_by("SEX", split_fun = drop_split_levels) %>%
summarize_row_groups(cfun = cfun_lvl2)
DM2 <- DM %>%
rename(USUBJID = ID) %>%
filter(COUNTRY %in% c("USA", "CHN", "BRA"))
tbl <- build_table(tbl_recipe, DM2)
tbl
## A: Drug X B: Placebo C: Combination
## ---------------------------------------------
## CHN 62 (73.8) 48 (64.0) 69 (74.2)
## F 34 (40.5) 29 (38.7) 31 (33.3)
## M 28 (33.3) 19 (25.3) 38 (40.9)
##
## USA 13 (15.5) 14 (18.7) 17 (18.3)
## F 8 (9.5) 6 (8.0) 10 (10.8)
## M 5 (6.0) 8 (10.7) 7 (7.5)
##
## BRA 9 (10.7) 13 (17.3) 7 (7.5)
## F 6 (7.1) 6 (8.0) 3 (3.2)
## M 3 (3.6) 7 (9.3) 4 (4.3)
utils::sessionInfo()
## R version 4.1.1 (2021-08-10)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 19042)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=English_United States.1252
## [2] LC_CTYPE=English_United States.1252
## [3] LC_MONETARY=English_United States.1252
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.1252
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] rtables_0.5.0 formatters_0.2.0 magrittr_2.0.2 dplyr_1.0.8
##
## loaded via a namespace (and not attached):
## [1] fansi_1.0.2 digest_0.6.29 assertthat_0.2.1 utf8_1.2.2
## [5] crayon_1.5.0 grid_4.1.1 R6_2.5.1 DBI_1.1.2
## [9] lifecycle_1.0.1 jsonlite_1.8.0 pillar_1.7.0 rlang_1.0.1
## [13] cli_3.1.1 vctrs_0.3.8 generics_0.1.2 ellipsis_0.3.2
## [17] glue_1.6.0 purrr_0.3.4 fastmap_1.1.0 compiler_4.1.1
## [21] pkgconfig_2.0.3 htmltools_0.5.2 tidyselect_1.1.2 tibble_3.1.6
@freestatman great to see rtables usage and interest 'in the wild'.
What you're describing isn't currently possible without hacky workarounds (your approach being one of the possible ways to do it that come to mind).
That said, this exact feature IS already on our roadmap for rtables development, so we agree that it is a good idea for a feature and it should land in an rtables near you sometime this year.
@freestatman This feature has been added to the development version (found here on github) and should be in the next CRAN release (no hard date scheduled yet, though probably soonish). See section_div in ?split_rows_by
lyt <- basic_table() %>%
+ split_rows_by("ARM", section_div = "-") %>%
+ split_rows_by("STRATA1", section_div = " ") %>%
+ analyze("AGE")
>
> tbl <- build_table(lyt, DM)
> tbl
all obs
————————————————————————
A: Drug X
A
Mean 32.53
B
Mean 35.46
C
Mean 36.34
------------------------
B: Placebo
A
Mean 32.30
B
Mean 32.42
C
Mean 34.45
------------------------
C: Combination
A
Mean 35.76
B
Mean 34.39
C
Mean 33.54
I'll close this issue, please give it a try and feel free to reopen the issue if this doesn't meet your needs.