Home > Net >  Producing a Word document using RMarkdown with programmatically-generated, interleaved, headers and
Producing a Word document using RMarkdown with programmatically-generated, interleaved, headers and

Time:02-28

Background: Using Purrr to filter a dataset and plot a series of graphs using ggplot (in RMarkdown, for Shiny)

Following the resolution of the previous question, above, I now have a .Rmd file that will produce a Word document with section headers, graphs, and a table of contents.

The following problems remain:

  1. The section headers and graphs are not interleaved. What I currently have is:

header1

header2

header3

graph1

graph2

graph3

How should my code be amended to produce:

header1

graph1

header2

graph2

header3

graph3

instead?

  1. The word document includes numbers in square brackets, e.g. "[[1]]", "[[2]]", etc, which I believe get printed with the graphs. How can these be removed?

  2. For each graph I'd like a boilerplate sentence that includes a statement about the data, specifically the number of datapoints that lie outside the dotted lines /- 2SD from the mean. I've tried adding it by including e.g.

report.data %>% 
dplyr::filter(identifier == x) %>%
paste(eval("r sum(result < mean(result) - 2 * sd(result))"), " results out of bounds.") 

in the function, but this turns the graphs into text(!).

As always, any help or advice that can be offered would be greatly appreciated - thank you for reading!

Script to generate example data and produce the report:

library(dplyr)
set.seed(1234)

test1.level1.analyser1 <- data.frame(
  result = rnorm(25, mean = 2.5, sd = 0.2), 
  test = c("test1"), 
  level = c("level1"), 
  sample.no = c(1:25), 
  analyser = c("analyser1")
  )

test1.level1.analyser2 <- data.frame(
  result = rnorm(25, mean = 2.6, sd = 0.1), 
  test = c("test1"), 
  level = c("level1"), 
  sample.no = c(1:25), 
  analyser = c("analyser2")
  )

test1 <- rbind(test1.level1.analyser1, test1.level1.analyser2)

test2.level1.analyser1 <- data.frame(
  result = rnorm(25, mean = 10, sd = 2), 
  test = c("test2"), 
  level = c("level1"), 
  sample.no = c(1:25), 
  analyser = c("analyser1")
  )

test2.level1.analyser2 <- data.frame(
  result = rnorm(25, mean = 9.5, sd = 0.75), 
  test = c("test2"), 
  level = c("level1"), 
  sample.no = c(1:25), 
  analyser = c("analyser2"))

test2.level2.analyser1 <- data.frame(
  result = rnorm(25, mean = 30, sd = 1.8), 
  test = c("test2"), 
  level = c("level2"), 
  sample.no = c(1:25), 
  analyser = c("analyser1")
  )

test2.level2.analyser2 <- data.frame(
  result = rnorm(25, mean = 25, sd = 0.75), 
  test = c("test2"), 
  level = c("level2"), 
  sample.no = c(1:25), 
  analyser = c("analyser2"))
test2.level2 <- rbind(test2.level2.analyser1, test2.level2.analyser2)

test2 <- rbind(test2.level1, test2.level2)

write.csv(test1, "test1.csv", row.names = FALSE)
write.csv(test2, "test2.csv", row.names = FALSE)

###
report.data <- rbind(test1, test2) %>% mutate(identifier = paste(test, level, sep = " ")) 
rmarkdown::render("report.Rmd", params = list(report.data = report.data), output_file = "intersite.comparison.report.doc")

The report.Rmd file:

---
title: "Inter-site IQC Comparison Report"
output: word_document
toc: yes
---

```{r setup, include=FALSE, comment = "", results = 'asis', echo = FALSE}
library(dplyr)
library(ggplot2)
library(purrr)
knitr::opts_chunk$set(echo = FALSE)

 my_plot <- function(df) {
    ggplot(df, aes(x = sample.no, y = result))  
    geom_point(aes(colour = analyser))  
    geom_hline(aes(yintercept = mean(result)   2 * sd(result)), colour = "red", linetype = "dashed")  
    geom_hline(aes(yintercept = mean(result) - 2 * sd(result)), colour = "red", linetype = "dashed")  
    theme_classic()  
    theme(legend.title = element_blank())  
    labs(
      # the title above the plot, based on information in the filtered df
      title = paste0("Inter-site comparison for ", unique(df$identifier)),
      x = "Sample number",
      y = "Result",
      # the text below, based on data in the filtered data frame
      caption = paste0("Caption here."))  
    expand_limits(y = 0)  
    coord_cartesian(xlim = c(0, max(df$sample.no)   2))      
    theme(
      # configure the caption / sentence below
      plot.caption=element_text(size=12, hjust = 0, margin = margin(t=20)),
      # add some buffer at bottom as spacing between plots
      plot.margin = margin(b=50)
    )
}
```

```{r, comment = "", results = 'asis', echo = FALSE}
purrr::map(unique(report.data$identifier),
                           function(x) {
                             #section heading
                             cat("#", (x), "\n")
                             # filter data before passing it to the plot function
                             report.data %>% 
                               dplyr::filter(identifier == x) %>%
                               my_plot()
                             #report.data %>% 
                               #dplyr::filter(identifier == x) %>%
                               #paste(eval("r sum(result < mean(result) - 2 * sd(result))"), " results out of bounds.")
                           }
)
```

EDIT: the current version of the code for the map function, following Sean van der Merwe's kind advice, below:

purrr::map(unique(report.data$identifier),
                           function(x) {
                             #section heading
                             cat("#", (x), "\n")
                             cat("\n\n")
                             # filter data before passing it to the plot function
                             report.data %>% 
                               dplyr::filter(identifier == x) %>%
                               my_plot() %>% print()
                             cat("\n\n")
                             #report.data %>% 
                               #dplyr::filter(identifier == x) %>%
                               #paste(eval("r sum(result < mean(result) - 2 * sd(result))"), " results out of bounds.")
                           }
) -> results

CodePudding user response:

Edit:

Try myplot() %>% print() perhaps. You need to actually send the plots to the output with ggplot.

Sorry for not seeing it earlier, this is the real crux: The reason the plots came out last, and at all, was because they were the output of the map function so they were being stored by map and output as a group after all the processing.

Original thoughts:

I often interleave results in similar ways. I believe your issue may be related to not having enough "\n"s. When writing markdown normally you would leave a line open between paragraphs, so here the markdown you are generating programmatically must have "\n\n" to indicate the end of the current line and the open line below. That also applies after the plot and after the results.

  • Related