Search code examples
rr-markdownr-highcharterhtmltools

Print single charts via loop with highcharter in rmarkdown


I would like to print single charts created in a for loop as tabbed content using the packages rmarkdown and highcharter.

So far i have only succeeded in displaying all the graphics in one tab.

The problem seems to be known (offline plots in for loops). However, I did not manage to apply the suggested solutions to my code.

Here is a minimal example:

---
title: "test"
output: html_document
---

```{r setup, include=FALSE}
#libraries
library(tidyverse)
library(highcharter)
library(htmltools)

#data
mydata <- data.frame(year  = c("2018", "2018", "2019", "2020"),
                 license = c("CC BY", "CC BY-NC", "CC BY", "CC BY"),
                 cost = c(1000, 1500, 2000, 1000))

#functions
group_by_license <- function(x) {
  x %>%
    group_by(license) %>%
    summarise(cost = sum(cost))
}
```

### license {.tabset .tabset-fade}

```{r mydata-license, results='asis', echo=F}
#data transformation
mydata_year <- split(mydata, mydata$year)

mydata_license <- lapply(mydata_year, group_by_license)

#chart
mychart <- function(i) {
  hchart(mydata_license[[i]],"pie", hcaes(x = license, y = cost)) %>%
    hc_title(text = paste0("My Data ", i))
}

#loop
a <- tagList()

for(i in unique(mydata$year)) {
  cat("#### ", i, "\n \n")
  a[[i]] <- mychart(i)
}

a
```

All three created charts are displayed in the last tab whereas the first two tabs are empty:

plots generated in the last tab

empty first tab

I would like to display each plot in the corresponding tab (graphic for 2018 in the 2018 tab etc.).

I also tried print which did not work and either showed no result or the HTML code of the chart but no graphic: see tried solutions here.


Solution

  • You are right. The issue and the solution seems to be the same as in other posts, see e.g. my answer on Using ggplotly and DT from a for loop in Rmarkdown but it's the first time I apply it to highcharter:

    1. To put you charts in separate tabs you have to print the charts inside the for loop. In your code you output all charts at the end of the chunk, hence they are all put in the last tab.

    2. Inside your for loop use print(htmltools::tagList( mychart(i) ) to print your charts

    3. Finally, to make this work we need another step to ensure that all the required JS dependencies are added to your Rmd which can be achieved by calling highchart(). I have put this in a separate chunk for which I set include=FALSE.

      ---
      title: "test"
      output: html_document
      ---
      
      ```{r setup, include=FALSE}
      #libraries
      library(tidyverse)
      library(highcharter)
      library(htmltools)
      
      #data
      mydata <- data.frame(year  = c("2018", "2018", "2019", "2020"),
                       license = c("CC BY", "CC BY-NC", "CC BY", "CC BY"),
                       cost = c(1000, 1500, 2000, 1000))
      
      #functions
      group_by_license <- function(x) {
        x %>%
          group_by(license) %>%
          summarise(cost = sum(cost))
      }
      ```
      
      ```{r include=FALSE}
      # Init Step to make sure that the dependencies are loaded
      highchart()
      ```
      
      ### license {.tabset .tabset-fade}
      
      ```{r mydata-license, results='asis', echo=F}
      mydata_year <- split(mydata, mydata$year)
      
      mydata_license <- lapply(mydata_year, group_by_license)
      
      mychart <- function(i) {
        hchart(mydata_license[[i]],"pie", hcaes(x = license, y = cost)) %>%
          hc_title(text = paste0("My Data ", i))
      }
      
      for(i in unique(mydata$year)) {
        cat("#### ", i, "\n \n")
        print(
          htmltools::tagList( mychart(i) )
        )
      }
      

    enter image description here