Skip to content
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

Guidance on how to generate figures and tables in a for loop (DRY principle) #156

Open
kelliemac opened this issue May 22, 2024 · 5 comments
Assignees

Comments

@kelliemac
Copy link
Contributor

kelliemac commented May 22, 2024

To follow the DRY (don't repeat yourself) principle, it is sometimes helpful to generate figures and tables in a for loop. For example, in the B-cell reports we are usually generating the same tables and figures repeatedly for different endpoints.

I think this challenge probably also applies in other assays. One approach is as follows:

``{r prepare-for-iterating-over-endpoints, results='asis'}

insert_fig_subchunk <- function(fig, fig_chunk_name, fig_caption_short, fig_caption_long) {
  
  fig_deparsed <- paste0(deparse(function(){fig}), collapse = '')
  fig_sub_chunk <- paste0(
    "\n```{r fig-", fig_chunk_name, ', ', 
    "fig.scap='", fig_caption_short, "', ",
    "fig.cap='", fig_caption_long, "'}",
    "\n(", fig_deparsed, ")()", "\n```\n")
  cat(knit(text = knit_expand(text = fig_sub_chunk), quiet = TRUE))
  
}

fig_caption_common_text <- 'Some description of the figure content that applies to every figure, such as the color schemes/shapes/methods used'

endpoint_list <- c('Percent of IgG B-cells that are antigen-specific', 'Percent of IgG B-cells that are VRC01-class')
``


``{r iterate-over-endpoints, results='asis'}

  for (endpoint in endpoint_list) {
    
    cat('## ', endpoint, ' \n') # subsection title
    
    # main figure
    fig_caption_short <- endpoint
    fig_caption_long <- paste0(endpoint, ". ", fig_caption_common_text)
    fig <- plot_responses(endpoint) # this function defined elsewhere
    fig_chunk_name <- gsub(' ', '-', endpoint)
    insert_fig_subchunk(fig, fig_chunk_name, fig_caption_short, fig_caption_long)
    
    cat("\n\n\\pagebreak\n")
    
    # tables  
    tabulate_response_timepoint_comparisons(endpoint) # this function defined elsewhere
    tabulate_response_group_comparisons(endpoint) # this function defined elsewhere
    
    cat("\n\n\\pagebreak\n")
    
  }
``

Is this broadly applicable enough that it would be helpful to incorporate some version of this into the report template?

If so, any improvements to suggest?

@kelliemac
Copy link
Contributor Author

@mayerbry we discussed this yesterday, would be great to have your thoughts.

@kelliemac kelliemac self-assigned this Sep 4, 2024
@kelliemac
Copy link
Contributor Author

A better example from conversation with Bryan on July 31st:

insert_fig_subchunk <- function(fig, fig_chunk_name, fig_caption_short, fig_caption_long) {
  
  fig_deparsed <- paste0(deparse(function(){fig}), collapse = '')
  fig_sub_chunk <- paste0(
    "\n```{r fig-", fig_chunk_name, ', ', 
    "fig.scap='", fig_caption_short, "', ",
    "fig.cap='", fig_caption_long, "'}",
    "\n(", fig_deparsed, ")()", "\n```\n")
  cat(knit(text = knit_expand(text = fig_sub_chunk), quiet = TRUE))
  
}

for (endpoint in endpoint_list) {
  
  cat('## ', endpoint, ' \n')
  
  ### main figure
  fig <- plot_responses(endpoint)
  fig_chunk_name <- gsub(' ', '-', endpoint)
  fig_caption_short <- endpoint
  fig_caption_long <- paste0(endpoint, ". ", plot_description_details)
  insert_fig_subchunk(fig, fig_chunk_name, fig_caption_short, fig_caption_long)

  ### table
  tab_label <- endpoint
  tab_caption_short <- endpoint
  tab_caption_long <- paste0(endpoint, ". ", tab_description_details)
  tab <- df %>%
      kable(format = output_type,
            caption = tab_caption_long,
            caption_short = tab_caption_short,
            label = tab_label)
  if (output_type == "latex") {
    cat(tab)
  } else {
    cat(knit_print(tab))
  }
  
  cat("\n\n \\clearpage \n")
  
}

@lemireg
Copy link

lemireg commented Oct 24, 2024

Thank you to Kellie's great TIOT on Oct 24, 2024 (and @asatofh for organizing) we had some great brainstorming related to this topic! I'm tagging folks who can share the relevant code, packages and/or challenges so we can provide guidance on creating multiple similar figures and/or tables at once. Knowing other people's blockers and challenges is really helpful so we don't all repeat the same issues in silos:

@at-crx Amanda shared some of her experiences with the challenges trying to create figures in a loop (issues: trying to reference figures, and the possibility of mismatching inputs when they're in the form of independent lists. for example a list of captions and a list of plot titles, etc.)
@brborate Bhavesh mentioned the use of purrr::map function to get all the figures as a list (re: ways to create objects to input into the for loops)
@bneradil Moni discussed HVTN's practices which include an alternative way to (is there code that can be shared to see this example?)
@valduran18 shared you can create dataframes with a column of lists of datasets, a column of text captions, and a column of list of figures. I think this is a great idea for debugging and viewing. and that this would be relevant for STPs (can you link git issues across repos? do we want to do that to create visibility for any specific STP repos?)

Would love to see relevant code! So please share! I am currently working on a report using these methods so any code or further thoughts shared sooner rather than later are appreciated and will be referenced for specific reports as well as general guidance for all of us. Thank you all and especially @kelliemac for the presentation, and great conversation!

@lemireg
Copy link

lemireg commented Oct 24, 2024

Courtesy of @bneradil

As described hvtnReports has a vignette on caption creation here:https://github.com/FredHutch/hvtnReports/blob/main/vignettes/tlf_captions.md
And our RMD skeleton is here: https://github.com/FredHutch/hvtnReports/blob/main/inst/rmarkdown/templates/vtn_report/skeleton/skeleton.Rmd

@kelliemac
Copy link
Contributor Author

thank you @lemireg for capturing today's discussion!!!! this is really helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants