0

I'm trying to use RMarkdown/R Notebooks to produce an automated report based on a single dataset broken out by department. Intuitively, I want to use a for loop that filters the dataset to a single department, provides a title, displays a few graphs and tables specific to that deparment, and then produces a page break and starts with the next department.

Here's a reprex of what I have so far. Problems with the resulting code:

  1. There are blank spaces throughout, pretty sure related to the use of dev.off() and plot.new(). If I remove these, only the first plot prints and the titles print all together in a bunch at the beginning. If I include the dev.off and plot.new calls, then I get blank graphics placeholders.
  2. There are NA items throughout. I'm not sure why. They don't appear when running the code in RStudio, only in the resulting output.
  3. I can't get headers to work and act like H1, H2 etc. headers. They are rendered as code output.

Am I approaching this wrong? Should I not use a for loop, but do something else instead? If I take everything out of the loop and do it manually, it works great.

```
---
title: "Demo Notebook"
output:
  word_document: default
---

```{r echo=FALSE, message=FALSE, warning=FALSE, paged.print=TRUE, results= "asis"}
library(tidyverse)
library(knitr)

spp <- unique(iris$Species)

for (i in seq_along(spp)) {

  print(paste0("# Species: ", spp[i]))

  d <- iris %>%
    filter(Species == spp[i])

# one kind of plot
  p <- ggplot(d, aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_smooth() +
    ggtitle(spp[i])

  print(p)
  dev.off()
  plot.new()

# another plot
  q <- plot(d$Sepal.Length)
  print(q)
  dev.off()

# a table
  print(kable(head(d)))

}

```
datakritter
  • 590
  • 5
  • 19

1 Answers1

1

That seems to be more complicated than anticipated. I managed with this solution, using flextable and, for some reason, needed two types of page breaks to actually get one in the word document:

---
title: "Demo Notebook"
output:
  word_document: default
---
```{r setup, include=FALSE}
library(tidyverse)
library(flextable)
```


```{r, echo=FALSE, message=FALSE, warning=FALSE, results='asis', fig.height=3, out.width="50%"}
spp <- unique(iris$Species)

for (x in seq_along(spp)) {
  print(paste0("# Species: ", spp[x]))
  d <- iris %>% filter(Species == spp[x])
  cat("\n\n")
  # one kind of plot
  p1 <- ggplot(d, aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_smooth() +
    ggtitle(spp[x])
  plot(p1)
  cat("\n\n")

  # another plot
  plot(d$Sepal.Length)
  cat("\n")

  # a table
  ft <- d[1:10, ] %>%
    flextable() %>%
    align(part = "all") %>% # left align
    set_caption(caption = "Table 1: Example") %>%
    font(fontname = "Calibri (Body)", part = "all") %>%
    fontsize(size = 10, part = "body") %>%
    theme_booktabs() %>% # default theme
    autofit()
  cat("\n")
  cat(paste("\n```{=openxml}",
    format(ft, type = "docx"),
    "```\n", sep = "\n"))

  cat("\n\n\\pagebreak\n")
  cat('<div style="page-break-before: always;" />')
}

```
user12728748
  • 8,106
  • 2
  • 9
  • 14
  • This works much better! And flextable produces prettier tables than kable did, so thank you. However, headers are still displaying as code: '[1] “# Species: versicolor”' instead of as an actual header in Word. Any ideas? – datakritter Feb 14 '20 at 19:50
  • I almost solved the header problem using html: print(paste0("

    # Species: ", spp[x], "")). However, a [1]" floats above my title and a random " mark appears at the end of my title. Getting closer, though.

    – datakritter Feb 14 '20 at 19:58