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:
- 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?
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?
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.