FMM
FMM

Reputation: 2015

Print ggplot2 and lm objects in a loop in RMarkdown

This is a follow-up question to this one.

In the aforementioned question I could nicely implement a heading creating and the printing of a ggplot2 object in a loop.

Now I have a new problem: I need to print the summary of a model in the loop too. The problem is that it doesn't work if I have the asis option.

Any ideas?

[Reprex:]

---
title: "Untitled"
output:
  html_document:
    theme: united
    highlight: tango
    toc: true
    toc_float:
      collapsed: false
      smooth_scroll: false
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
```

```{r}
library(dplyr)
library(ggplot2)

df <- datasets::iris %>% 
  dplyr::as_tibble()
```

```{r species_loop, results='asis'}
for(i in c("setosa", "versicolor", "virginica")) {

  cat(paste0("\n\n## ", i, "\n"))

  df_filtered <- df %>% 
    dplyr::filter(Species == i)

  p <-  df_filtered %>% 
    ggplot2::ggplot(ggplot2::aes(Sepal.Length, Petal.Length)) + 
    ggplot2::geom_point()
  print(p)

  my_model <- lm(Sepal.Length ~ Petal.Length, data = df_filtered)

  summary(my_model) %>% 
    print()
}
```

## I need the printing output of the model to look like this:

```{r}
df_filtered <- df %>% 
    dplyr::filter(Species == "setosa")

my_model <- lm(Sepal.Length ~ Petal.Length, data = df_filtered)

  summary(my_model) %>% 
    print()
```

Upvotes: 2

Views: 2242

Answers (2)

aosmith
aosmith

Reputation: 36086

It looks like this is a case for a template document and knitr::knit_expand(). A canonical answer is here. Working with strings sent me to this answer, as well, since I wasn't entire sure how the "{{" notation worked in this approach.

This approach involves making a template R markdown document in the same directory. Depending on whether you want to include code chunks or need chunk names, that could look something like:

## {{species}}

```{r species_loop-{{species}}, echo = FALSE}
df_filtered <- df %>% 
     dplyr::filter(Species == "{{species}}")

df_filtered %>% 
     ggplot2::ggplot(ggplot2::aes(Sepal.Length, Petal.Length)) + 
     ggplot2::geom_point()

my_model <- lm(Sepal.Length ~ Petal.Length, data = df_filtered)
summary(my_model)
```

Then your master document code could look like:

```{r}
library(dplyr)
library(ggplot2)

df <- datasets::iris %>% 
  dplyr::as_tibble()
```

```{r, include = FALSE}
src <- lapply(c("setosa", "versicolor", "virginica"),
             function(species) {
                  knitr::knit_expand(file = "template.Rmd")
             }
)
```

`r knitr::knit(text = unlist(src))`

Upvotes: 1

Corey Pembleton
Corey Pembleton

Reputation: 757

When I replace the summary() line with a tidymodel, you can pipe into a kable:

 print(broom::tidy(my_model) %>% knitr::kable())

You'll have to adjust the settings of the tidy() call to include more outputs, but its working for me:

enter image description here

full code:

for(i in c("setosa", "versicolor", "virginica")) {

  cat(paste0("\n\n## ", i, "\n"))

  df_filtered <- df %>% 
    dplyr::filter(Species == i)

  p <-  df_filtered %>% 
    ggplot2::ggplot(ggplot2::aes(Sepal.Length, Petal.Length)) + 
    ggplot2::geom_point()
  print(p)

  my_model <- lm(Sepal.Length ~ Petal.Length, data = df_filtered)

 print(broom::tidy(my_model) %>% knitr::kable())


}

Upvotes: 0

Related Questions