Tim Wilcox
Tim Wilcox

Reputation: 1331

Is there a way to use tabset for finished R markdown files

So I have 17 completely independent R markdown files. They run fine. However, I want to consolidate them into one and have a tabset so that the user can pick one and not all 17.

now, I know how to use tabset inside of each r markdown file. As an example, I create a lot of the charts have four iterations of it and so I use tabset to let the user pick which iteration. In this case, each iteration is based on a numerical threshold for employment.

as an example, I created two generic R markdowns and named test1 and test2. Using a third R markdown file (again, just file>new>R Markdown), how would I reference test1 and test2 in a tabset?

Upvotes: 0

Views: 756

Answers (1)

r2evans
r2evans

Reputation: 160397

There's no automated way to do it, but here's a hack using HTML iframes (for better or worse).

Up front, two assumptions:

  • all HTML files need to be complete, and if they are not "self-contained" then all paths (relative or absolute) must work for the parent HTML document as well; and

  • there can be a clear naming convention or known list of files to include; for here, I make all subordinate files named sub_*.html so that the parent document can find them easily, but there are many ways this part can be adjusted. As long as htmlfiles below can be generated smartly, you're good.

Create subordinate "pages"

I'll name this sub_base.Rmd:

---
title: "base"
output: html_document
---

```{r, echo = FALSE, message = FALSE}
plot(mpg ~ disp, data = mtcars, pch = 16)
```

Name: sub_ggplot2.Rmd:

---
title: "ggplot2"
output: html_document
---

```{r, echo = FALSE, message = FALSE}
library(ggplot2)
ggplot(mtcars, aes(disp, mpg)) + geom_point()
```

Parent document

I'll name it combine.Rmd:

---
title: "combined"
output: html_document
---

# Different Graphics {.tabset}

```{r results='asis', echo=FALSE}
htmlfiles <- list.files(".", pattern = "sub.*\\.html$", full.names = TRUE)
for (html in htmlfiles) {
  hdr <- gsub("^sub_", "", tools::file_path_sans_ext(basename(html)))
  cat(
    sprintf('## %s\n\n <iframe src="%s" title="%s frame" style="position:absolute;height:60%%;width:60%%;"></iframe>\n\n',
            hdr, html, hdr)
  )
}
```

The key is that you first need a header that includes the {.tabset} style applied to it, and then the loop needs to generate unique sub-headers. This can be done with a ## followed by subordinate ###, over to you and the rest of the combine document structure/aesthetics.

Render

rmarkdown::render("sub_base.Rmd")
rmarkdown::render("sub_ggplot2.Rmd")
rmarkdown::render("combine.Rmd")

Results

You may want to tune the iframe components to suit your needs, but they do present scrollbars when pages are large enough.

browser tab showing iframed tabsets

Files Sizes

In this example, I kept the default behavior of making the HTML files self-contained. With barely anything in the reports and two plots, this results in a distribution of 2.3M. This has the advantage that you need only distribute the single file: one combine.html is rendered, it has the contents of the subordinate documents embedded.

If you need to (for whatever reason) keep any of this not self-contained, then the distribution will change: in addition to needing multiple files and subdirs, the overall size is also larger: 12M for this example. (In this case, you would need to distribute all sub_*.html files and sub_*_files/ subdirs.)

Upvotes: 3

Related Questions