FlexDashboard Dynamic Tabset Creation

65 Views Asked by At

I'm trying to figure out a way to make an arbitrary amount of custom-sized tabs on a flex-dashboard tabset.

I found this post, which I was able to modify slightly to create a tab-set for a list of plots.

---
title: "Tab Tests"
output: 
  flexdashboard::flex_dashboard:
      orientation: rows
      vertical_layout: scroll
      smooth_scroll: yes
---

## Test {.tabset .tabset-fade}

```{r, eval = T, results='asis'}
library(data.table)
library(ggplot2)

data_lsdt <- list("one" = data.table("A" = 1:10, "B" = 1:10),
                  "two" = data.table("A" = 1:20, "B" = 1:20),
                  "three" = data.table("A" = 1:100, "B" = 1:100))

for (i in 1:length(data_lsdt)) {

  curr_gg <- ggplot(data = data_lsdt[[i]], aes(x = A, y = B)) + geom_point()
  
  cat(paste0('### ', names(data_lsdt)[i], '\n'))
  
  print(curr_gg)
  
  cat('\n\n')
}
```

This, however, doesn't allow me to change the size of the plotting area depending on the plot. For example, if I just hard-code these plots in, I can specify the fig.height and fig.weight.

---
title: "Tab Tests2"
output: 
  flexdashboard::flex_dashboard:
      orientation: rows
      vertical_layout: scroll
      smooth_scroll: yes
---

```{r}
library(data.table)
library(ggplot2)

data_lsdt <- list("one" = data.table("A" = 1:10, "B" = 1:10),
                  "two" = data.table("A" = 1:20, "B" = 1:20),
                  "three" = data.table("A" = 1:100, "B" = 1:100))

plots_lsgg <- lapply(data_lsdt, function(x) {
  ggplot(data = x, aes(x = A, y = B)) + geom_point()
})
```

## Test {.tabset .tabset-fade}

### One

```{r, fig.width=10, fig.height=10}
plots_lsgg$one
```

### Two

```{r, fig.width=2, fig.height=2}
plots_lsgg$two
```

### Three

```{r, fig.width=4, fig.height=10}
plots_lsgg$three
```

I found some information about subchunkify here and here for markdown, and have been trying to modify that, but can't get what I want.

In this example, when I knit the document, I get the tabs, but the plot is not rendered:

---
title: "Tab Tests4"
output: 
  flexdashboard::flex_dashboard:
      orientation: rows
      vertical_layout: scroll
      smooth_scroll: yes
---

```{r buildFxn}
fdSubchunkify <- function(g, fig_height=7, fig_width=5, id = NULL, title_v = "Title") {
  #' FD Subchunkify
  #' @description Output a flexdashboard plotting chunk. Modified from SO code:
  #' https://stackoverflow.com/questions/15365829/dynamic-height-and-width-for-knitr-plots/47339394#47339394
  #' https://stackoverflow.com/questions/61620768/rmarkdown-explicitly-specify-the-figure-size-of-a-plot-within-a-chunk
  #' Had to modify the paste0() call for sub_chunk because r markdown was giving warnings about mismatched ticks for some 
  #' @param g plot to place in chunk
  #' @param fig_height height of chunk
  #' @param fig_width width of chunk
  #' @param id optional chunk ID to help with unique labels
  #' @param title_v optional title to use instead of 
  #' @export
  #'
  
  ### Deparse plot
  g_deparsed <- paste0(deparse(
    function() {g}
  ), collapse = '')
  
  ### Make chunk id be title if not provided
  if (is.null(id)) id <- gsub(" .*$", "", title_v)
  
  ### Build Tab Title
  one_v <- paste0('
                  #', '## ', title_v, '
                  ')
  
  ### Construct code chunk header
  two_v <- paste0('
                  `', '``{r sub_chunk_', id, '_', floor(runif(1) * 10000000),
                  ', fig.height=', fig_height, ', fig.width=', fig_width, ', echo = F}\n
                  ')
  
  ### Insert plot
  three_v <- paste0('
                    \n\n (',
                    g_deparsed
                    , ")()")
  
  ### Close code chunk
  four_v <- paste0('
                   \n`', '``
                   ')
  
  ### Combine
  out_v <- paste(trimws(one_v), trimws(two_v), trimws(three_v), trimws(four_v), sep = "\n")
  
  ### Output chunk
  cat('\n\n')
  cat(trimws(out_v))
  cat('\n\n')
  
} # subchunkify
```

## Test {.tabset .tabset-fade}

```{r, eval = T, results='asis'}
library(data.table)
library(ggplot2)

data_lsdt <- list("one" = data.table("A" = 1:10, "B" = 1:10),
                  "two" = data.table("A" = 1:20, "B" = 1:20),
                  "three" = data.table("A" = 1:100, "B" = 1:100))

dims_lsv <- list("height" = c(10, 2, 10),
                 "width" = c(10, 2, 4))

for (i in 1:length(data_lsdt)) {
  
  curr_gg <- ggplot(data = data_lsdt[[i]], aes(x = A, y = B)) + geom_point()
  
  fdSubchunkify(g = curr_gg, fig_height = dims_lsv$height[i], fig_width = dims_lsv$width[i],
                title_v = names(data_lsdt)[i])
  
}

```

fdSubchunkifyHTMLResult

If I run the code in the console, the output looks like it should work, but obviously I'm missing something:

### one
```{r sub_chunk_one_305773, fig.height=10, fig.width=10, echo = F}
(function () {    g})()
```



### two
```{r sub_chunk_two_4745726, fig.height=2, fig.width=2, echo = F}
(function () {    g})()
```



### three
```{r sub_chunk_three_2213424, fig.height=10, fig.width=4, echo = F}
(function () {    g})()
```

I believe it has something to do with the newlines and/or whitespace, but I'm not entirely sure how to fix it or determine if that's even the issue. I took the subchunkify out of the function and put it into a loop to try to test a few modifications

---
title: "Tab Tests"
output: 
  flexdashboard::flex_dashboard:
      orientation: rows
      vertical_layout: scroll
      smooth_scroll: yes
---

## Test {.tabset .tabset-fade}

```{r, eval = T, results='asis'}
library(data.table)
library(ggplot2)

data_lsdt <- list("one" = data.table("A" = 1:10, "B" = 1:10),
                  "two" = data.table("A" = 1:20, "B" = 1:20),
                  "three" = data.table("A" = 1:100, "B" = 1:100))

for (i in 1:length(data_lsdt)) {
  
  curr_gg <- ggplot(data = data_lsdt[[i]], aes(x = A, y = B)) + geom_point()
  
  g_deparsed <- paste0(deparse(
    function() {curr_gg}
  ), collapse = '')
  
  cat(paste0('### ', names(data_lsdt)[i], '\n'))
  
  cat("```{r, fig.width = 5, fig.height = 10}\n")
  cat(g_deparsed)
  cat("```\n")
  cat('\n')

}

```

Method 1: Newline at end of each cat() returns tabs, but no plot. Looks like a newline between end of code block header and code didn't get returned

Method1

Method 2: Add an explicit new line between code block header and code. Returns tabs still, other output is slightly different.

cat("```{r, fig.width = 5, fig.height = 10}\n")
cat("\n")
cat(g_deparsed)
cat("```\n")
cat('\n')

Method2

Method3: Add another explicit new line after the code and before final "triple-tick. This one messes up the tabs.

cat("```{r, fig.width = 5, fig.height = 10}\n")
cat("\n")
cat(g_deparsed)
cat("\n")
cat("```\n")
cat('\n')

Method3

I've tried a few other similar methods to no avail. Appreciate any ideas!

0

There are 0 best solutions below