-
Notifications
You must be signed in to change notification settings - Fork 18
close #105 adding slides and docx #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 36 commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
cfeccec
init commit
shajoezhu 10e9709
update autoslider example
shajoezhu 3657573
update
shajoezhu 6af3487
update
shajoezhu f415ad7
update dep
shajoezhu a421933
rm file
shajoezhu 431cf1d
Update DESCRIPTION
shajoezhu e3549f6
Apply suggestions from code review
shajoezhu 6c63d94
Apply suggestions from code review
shajoezhu 5210c84
update
shajoezhu 18f1c90
init commit
shajoezhu 44b9c68
update autoslider example
shajoezhu f589f61
update
shajoezhu c0b6510
update
shajoezhu b4eafee
update dep
shajoezhu 04acf3f
rm file
shajoezhu 2135a92
Update DESCRIPTION
shajoezhu 6b3310a
Apply suggestions from code review
shajoezhu fb47cfd
Apply suggestions from code review
shajoezhu 451533f
update
shajoezhu 9d357ea
Merge branch 'main' of github.com:shajoezhu/pharmaverse_examples
shajoezhu 77b6bde
update wordlist
shajoezhu fa47028
Merge branch 'main' into main
rossfarrugia b4025d4
update wordlist
shajoezhu bfe3ad8
Merge branch 'main' of github.com:shajoezhu/pharmaverse_examples
shajoezhu 5572de7
mv documents
shajoezhu 1adbb16
change folder
shajoezhu 3e7808f
update, mv files
shajoezhu 7a8fd77
Update digit_files/docx.qmd
shajoezhu d6ab6b1
Merge branch 'main' of github.com:shajoezhu/pharmaverse_examples
shajoezhu 9e93d42
update and add R fileS
shajoezhu 58a1e85
change to #
shajoezhu f1266bd
update stle
shajoezhu 07976b8
updat ewordlist
shajoezhu 3c648fa
update style
shajoezhu d3be082
udpate style
shajoezhu a6835ec
sort the wordlist
shajoezhu b800352
Apply suggestions from code review
shajoezhu 2bd7895
Merge branch 'main' of github.com:shajoezhu/pharmaverse_examples
shajoezhu 237499e
rname file
shajoezhu 0e6d433
update wordlist
shajoezhu 92ad07a
update file names
shajoezhu 29b3166
update and check
shajoezhu b8f6009
only do tdm
shajoezhu 9331c44
update style
shajoezhu c11d80f
update style
shajoezhu 00b2da4
minor update
shajoezhu 534b63e
minor update
shajoezhu 05c6de1
rm lines
shajoezhu ceb463b
restyle“
shajoezhu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ Authors@R: | |
| person("David", "Blair", role = "aut"), | ||
| person("Daniel D.", "Sjoberg", , "[email protected]", role = "aut", comment = c(ORCID = "0000-0003-0862-2018")), | ||
| person("Fanny", "Gautier", role = "aut", comment = c(ORCID = "0009-0004-3581-0131")), | ||
| person("Joe", "Zhu", role = "aut", comment = c(ORCID = "0000-0001-7566-2787")), | ||
| person("Aksel", "Thomsen", , "[email protected]", role = "aut"), | ||
| person("Shiyu", "Chen", , "[email protected]", role = "aut"), | ||
| person("Rammprasad", "Ganapathy", , "[email protected]", role = "aut") | ||
|
|
@@ -21,8 +22,10 @@ URL: https://github.com/pharmaverse/examples | |
| Imports: | ||
| admiralonco, | ||
| admiral, | ||
| autoslider.core, | ||
| cards, | ||
| dplyr, | ||
| filters, | ||
| gtsummary, | ||
| lubridate, | ||
| labelled, | ||
|
|
@@ -36,6 +39,8 @@ Imports: | |
| pkglite, | ||
| reactable, | ||
| reactablefmtr, | ||
| rtables, | ||
| rtables.officer, | ||
| rlistings, | ||
| sdtm.oak, | ||
| sparkline, | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| ## ----r setup------------------------------------------------------------------ | ||
| library(autoslider.core) | ||
| library(dplyr) | ||
|
|
||
| # 1. Load ALL necessary packages | ||
| library(rtables) # For append_topleft() | ||
| library(assertthat) # For assert_that() you had issues with before | ||
| library(tern) | ||
|
|
||
| # define path to the yml files | ||
| spec_file <- file.path("metadata/spec.yml") | ||
|
|
||
| filters_file <- file.path("metadata/filters.yml") | ||
| # load all filters | ||
| filters::load_filters(filters_file, overwrite = TRUE) | ||
|
|
||
| ## ----r, table----------------------------------------------------------------- | ||
| # read data | ||
| data <- list( | ||
| "adsl" = eg_adsl %>% | ||
| mutate( | ||
| FASFL = SAFFL, # add FASFL for illustrative purpose for t_pop_slide | ||
| # DISTRTFL is needed for t_ds_slide but is missing in example data | ||
| DISTRTFL = sample(c("Y", "N"), size = length(TRT01A), replace = TRUE, prob = c(.1, .9)) | ||
| ) %>% | ||
| preprocess_t_ds(), # this preproccessing is required by one of the autoslider.core functions | ||
| "adae" = eg_adae, | ||
| "adtte" = eg_adtte, | ||
| "adrs" = eg_adrs, | ||
| "adlb" = eg_adlb | ||
| ) | ||
|
|
||
| # create outputs based on the specs and the functions | ||
| outputs <- spec_file %>% | ||
| read_spec() %>% | ||
| # we can also filter for specific programs: | ||
| filter_spec(., program %in% c("t_ds_slide", "t_dm_slide")) %>% | ||
| # these filtered specs are now piped into the generate_outputs function. | ||
| # this function also requires the data | ||
| generate_outputs(datasets = data) %>% | ||
| # now we decorate based on the specs, i.e. add footnotes and titles | ||
| decorate_outputs( | ||
| version_label = NULL | ||
| ) | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| outputs$t_dm_slide_ITT | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| outputs %>% | ||
| generate_slides( | ||
| outfile = "presentation.pptx", | ||
| template = file.path(system.file(package = "autoslider.core"), "/theme/basic.pptx"), | ||
| table_format = autoslider_format | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| --- | ||
| title: "Slides" | ||
| order: 1 | ||
| --- | ||
|
|
||
| ```{r setup script, include=FALSE, purl=FALSE} | ||
| invisible_hook_purl <- function(before, options, ...) { | ||
| knitr::hook_purl(before, options, ...) | ||
| NULL | ||
| } | ||
| knitr::knit_hooks$set(purl = invisible_hook_purl) | ||
| ``` | ||
|
|
||
|
|
||
| # Introduction | ||
|
|
||
|
|
||
| `AutoslideR` functions that are used for slide rendering and workflow are already open-sourced with the `autoslider.core` package. In this example, we show the general `autoslideR` workflow, how you can create functions from our templates and produce study-specific outputs, and how you can integrate them into the `autoslideR` framework to automate slide generation. | ||
|
|
||
|
|
||
| # Background | ||
|
|
||
| At its heart, `autoslideR` was created to tackle the inefficiencies and error-proneness of manual slide generation in clinical trials. It automates the creation of slides, significantly reducing the amount of work and time required, minimizing the risk of errors from manual data entry, and alleviating stress during demanding reporting periods. | ||
|
|
||
| `autoslideR` works by transforming your analysis data (SDTM, ADaM, raw, etc.) into standardized Table/Listing/Graph (TLG) objects. These objects are then decorated with titles, subtitles, and footnotes, positioning them at desired locations. With the addition of placeholder slides, the resulting PPTX file is ready for use in meetings. | ||
rossfarrugia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| # Prerequisites | ||
|
|
||
| First and foremost, you need to have the `autoslider.core` package installed, and you need to have data available. In this example, it uses example data stored in the `autoslider.core` package. The data needs to be stored in a named list (in this particular example, dataset names correspond to ADaM data sets). | ||
shajoezhu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ## File structure | ||
|
|
||
|
|
||
| The folder structure could look something like: | ||
|
|
||
| ``` | ||
| ├── programs | ||
| │ ├── run_script.R | ||
| │ ├── R | ||
| | | ├── template_functions.R | ||
| | | ├── output_functions.R | ||
| ├── outputs | ||
| ├── spec.yml | ||
| ├── filters.yml | ||
| ``` | ||
|
|
||
| The `autoslideR` workflow would be implemented in the `run_script.R` file. | ||
| This workflow does not require the files in `programs/R/`. | ||
| However, if custom `output_functions.R` are implemented, `programs/R/` would be the place to put them. | ||
|
|
||
| The `autoslideR` workflow has four main aspects: | ||
|
|
||
| ## The specifications `specs.yml` | ||
|
|
||
| This file contains the specifications of all outputs you would like to create. | ||
|
|
||
| For each output we define specific information, namely the program name, the footnotes & titles, the paper (this indicates the orientation, P for portrait and L for landscape, the number indicates the font size), the suffix and `args`. | ||
|
|
||
| It could look something like that: | ||
|
|
||
| ``` | ||
| - program: t_ds_slide | ||
| titles: Patient Disposition ({filter_titles("adsl")}) | ||
| footnotes: 't_ds footnotes' | ||
| paper: L6 | ||
| suffix: ITT | ||
| - program: t_dm_slide | ||
| titles: Patient Demographics and Baseline Characteristics | ||
| footnotes: 't_dm_slide footnote' | ||
| paper: L6 | ||
| suffix: ITT | ||
| args: | ||
| arm: "TRT01A" | ||
| vars: ["SEX", "AGE", "RACE"] | ||
|
|
||
shajoezhu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ``` | ||
|
|
||
| The program name refers to a function that produces an output. | ||
| This could be one of the template functions provided in `autoslider.core` or a custom function. See vignette [`adding_templates`](https://insightsengineering.github.io/autoslider.core/latest-tag/articles/adding_templates.html) for a detailed guide on using templates. | ||
|
|
||
| Titles and footnotes are added once the outputs are created. | ||
| We refer to that as decorating the outputs. | ||
|
|
||
| The suffix specifies the name of the filters that are applied to the data, before the data is funneled into the function (program). | ||
| The filters themselves are specified in the `filters.yml` file. | ||
|
|
||
| ## The filters `filters.yml` | ||
|
|
||
| In `filters.yml` we specify the names of the filters used across the outputs. | ||
| Each filter has a name (e.g. `FAS`), a title (`Full Analysis Set`), and then the filtering condition on a target dataset. | ||
| The filter title may be appended to the output title. For the `t_ds_slides` slide above all filter titles that target the adsl dataset would be included in the brackets. | ||
shajoezhu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| We would thus expect the title to read: "Patient Disposition (Full Analysis Set)" | ||
shajoezhu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| As you can see, we don't just have population filters, but also filters on serious adverse events. | ||
| We can thus produce SAE tables by just supplying the serious adverse events to the AE table function. | ||
| This concept generalizes also to `PARAMCD` values. | ||
|
|
||
|
|
||
| ``` | ||
| ITT: | ||
| title: Intent to Treat Population | ||
| condition: ITTFL == "Y" | ||
| target: adsl | ||
| type: slref | ||
| SAS: | ||
| title: Secondary Analysis Set | ||
| condition: SASFL == "Y" | ||
| target: adsl | ||
| type: slref | ||
| SE: | ||
| title: Safety Evaluable Population | ||
| condition: SAFFL == "Y" | ||
| target: adsl | ||
| type: slref | ||
| SER: | ||
| title: Serious Adverse Events | ||
| condition: AESER == "Y" | ||
| target: adae | ||
| type: anl | ||
|
|
||
| ``` | ||
|
|
||
| # AutoslideR typical workflow example | ||
|
|
||
| A typical workflow could look something like this: | ||
|
|
||
| ```{r setup} | ||
| library(autoslider.core) | ||
| library(dplyr) | ||
|
|
||
| # 1. Load ALL necessary packages | ||
| library(rtables) # For append_topleft() | ||
| library(assertthat) # For assert_that() you had issues with before | ||
| library(tern) | ||
|
|
||
| # define path to the yml files | ||
| spec_file <- file.path("metadata/spec.yml") | ||
|
|
||
| filters_file <- file.path("metadata/filters.yml") | ||
| # load all filters | ||
| filters::load_filters(filters_file, overwrite = TRUE) | ||
| ``` | ||
shajoezhu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
|
|
||
| ```{r, table} | ||
| # read data | ||
| data <- list( | ||
| "adsl" = eg_adsl %>% | ||
| mutate( | ||
| FASFL = SAFFL, # add FASFL for illustrative purpose for t_pop_slide | ||
| # DISTRTFL is needed for t_ds_slide but is missing in example data | ||
| DISTRTFL = sample(c("Y", "N"), size = length(TRT01A), replace = TRUE, prob = c(.1, .9)) | ||
| ) %>% | ||
| preprocess_t_ds(), # this preproccessing is required by one of the autoslider.core functions | ||
| "adae" = eg_adae, | ||
| "adtte" = eg_adtte, | ||
| "adrs" = eg_adrs, | ||
| "adlb" = eg_adlb | ||
| ) | ||
|
|
||
| # create outputs based on the specs and the functions | ||
| outputs <- spec_file %>% | ||
| read_spec() %>% | ||
| # we can also filter for specific programs: | ||
| filter_spec(., program %in% c("t_ds_slide", "t_dm_slide")) %>% | ||
| # these filtered specs are now piped into the generate_outputs function. | ||
| # this function also requires the data | ||
| generate_outputs(datasets = data) %>% | ||
| # now we decorate based on the specs, i.e. add footnotes and titles | ||
| decorate_outputs( | ||
| version_label = NULL | ||
| ) | ||
| ``` | ||
|
|
||
|
|
||
| We can have a look at one of the outputs stored in the outputs file: | ||
| ```{r} | ||
| outputs$t_dm_slide_ITT | ||
| ``` | ||
|
|
||
|
|
||
| ```{r} | ||
| outputs %>% | ||
| generate_slides( | ||
| outfile = "presentation.pptx", | ||
| template = file.path(system.file(package = "autoslider.core"), "/theme/basic.pptx"), | ||
| table_format = autoslider_format | ||
| ) | ||
| ``` | ||
|
|
||
| For the final product, when it includes more output, it may look like the following | ||
|
|
||
| {fig-align="center"} | ||
shajoezhu marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| ## ----r------------------------------------------------------------------------ | ||
| library(tern) | ||
| library(dplyr) | ||
| library(rtables.officer) | ||
|
|
||
| # Load example datasets | ||
| adsl <- pharmaverseadam::adsl | ||
| adlb <- pharmaverseadam::adlb | ||
|
|
||
| # Convert character variables to factors and handle missing levels | ||
| adsl <- df_explicit_na(adsl) | ||
| adlb <- df_explicit_na(adlb) | ||
|
|
||
| # Create a temporary file for the output | ||
| tf <- tempfile(fileext = ".docx") | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| adlb_f <- adlb %>% | ||
| dplyr::filter( | ||
| PARAM %in% c("Alanine Aminotransferase (U/L)", "Creatinine Kinase (U/L)") & | ||
| !(ACTARM == "B: Placebo" & AVISIT == "Week 2") | ||
| ) | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| afun <- function(x, .var, .spl_context, ...) { | ||
| n_fun <- sum(!is.na(x), na.rm = TRUE) | ||
| mean_sd_fun <- if (n_fun == 0) c(NA, NA) else c(mean(x, na.rm = TRUE), sd(x, na.rm = TRUE)) | ||
| median_fun <- if (n_fun == 0) NA else median(x, na.rm = TRUE) | ||
| min_max_fun <- if (n_fun == 0) c(NA, NA) else c(min(x), max(x)) | ||
|
|
||
| is_chg <- .var == "CHG" | ||
| is_baseline <- .spl_context$value[which(.spl_context$split == "AVISIT")] == "Baseline" | ||
| if (is_baseline && is_chg) n_fun <- mean_sd_fun <- median_fun <- min_max_fun <- NULL | ||
|
|
||
| in_rows( | ||
| "n" = n_fun, | ||
| "Mean (SD)" = mean_sd_fun, | ||
| "Median" = median_fun, | ||
| "Min - Max" = min_max_fun, | ||
| .formats = list("n" = "xx", "Mean (SD)" = "xx.xx (xx.xx)", "Median" = "xx.xx", "Min - Max" = "xx.xx - xx.xx"), | ||
| .format_na_strs = list("n" = "NE", "Mean (SD)" = "NE (NE)", "Median" = "NE", "Min - Max" = "NE - NE") | ||
| ) | ||
| } | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| lyt <- basic_table() %>% | ||
| split_cols_by("ACTARM", show_colcounts = TRUE, split_fun = keep_split_levels(levels(adlb_f$ACTARM)[c(1, 2)])) %>% | ||
| split_rows_by("PARAM", | ||
| split_fun = drop_split_levels, label_pos = "topleft", | ||
| split_label = obj_label(adlb_f$PARAM), page_by = TRUE | ||
| ) %>% | ||
| split_rows_by("AVISIT", | ||
| split_fun = drop_split_levels, label_pos = "topleft", | ||
| split_label = obj_label(adlb_f$AVISIT) | ||
| ) %>% | ||
| split_cols_by_multivar( | ||
| vars = c("AVAL", "CHG"), | ||
| varlabels = c("Value at Visit", "Change from Baseline") | ||
| ) %>% | ||
| analyze_colvars(afun = afun) | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| result <- build_table(lyt, adlb_f) | ||
| result | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| main_title(result) <- "Alanine Aminotransferase Measurement" | ||
| subtitles(result) <- c("This is a subtitle.", "This is another subtitle.") | ||
| main_footer(result) <- "This is a demo table for illustration purpose." | ||
| prov_footer(result) <- "Program: demo_poc_docx.R\nDate: 2024-11-06\nVersion: 0.0.1\n" | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| flx_res <- tt_to_flextable(result) | ||
| export_as_docx(flx_res, | ||
| file = tf, | ||
| section_properties = section_properties_default(orientation = "landscape") | ||
| ) | ||
| flx_res | ||
|
|
||
| ## ----r------------------------------------------------------------------------ | ||
| cw <- propose_column_widths(result) | ||
| cw <- cw / sum(cw) | ||
| cw <- c(0.6, 0.1, 0.1, 0.1, 0.1) | ||
| spd <- section_properties_default(orientation = "landscape") | ||
| fin_cw <- cw * spd$page_size$width / 2 / sum(cw) | ||
|
|
||
| flex_tbl <- tt_to_flextable(result, | ||
| total_page_width = spd$page_size$width / 2, | ||
| counts_in_newline = TRUE, | ||
| autofit_to_page = FALSE, | ||
| bold_titles = TRUE, | ||
| colwidths = cw | ||
| ) | ||
|
|
||
| export_as_docx(flex_tbl, file = tf) | ||
| flex_tbl |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.