rmarkdown user input to select from a list

Viewed 955

I am trying to generate an RMarkdown document. I have a list freqsByYear and I would like the user to select from a drop down menu (or some similar method) and this will get stored as Q from here I can pass it to a ggplot function and make the plot as follows.

Q = "FNB1"

freqsByYear %>% 
  pluck(., Q) %>% 
  ggplot(aes(x = !!sym(Q), y = n, fill = n)) +
  geom_col() +
  facet_wrap(~YEAR)

However, I am not sure how to allow the user to select Q such that it updates. No calculations are required in the background since everything is already stored in the list so it will just be the user selecting which plot to display.

Rmarkdown:

---
title: "title"
author: Name
date: "`r format(Sys.time(), '%d %B, %Y')`"
output: 
 html_document:
   theme: flatly # default, cerulean, journal, flatly, darkly, readable, spacelab, united, cosmo, lumen, paper, sandstone, simplex, and yeti
   highlight: tango # default, tango, pygments, kate, monochrome, espresso, zenburn, haddock, breezedark, and textmate
   smart: true
   toc: true
   toc_depth: 2
   toc_float:
     collapsed: false
     smooth_scroll: false
   numbers_sections: true
   fig_width: 7
   fig_height: 6
   fig_caption: true
   df_print: paged
   code_folding: hide

   
   
#bibliography: bibliography.bib
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
set.seed(1234)
library(knitr)
library(kableExtra)
```


```{r}
Q = "AA1"

freqsByYear %>% 
  pluck(., Q) %>% 
  ggplot(aes(x = !!sym(Q), y = n, fill = n)) +
  geom_col() +
  facet_wrap(~YEAR)
```

Data:

freqsByYear <- list(LG1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 2L, 2L, 2L
), LG1 = c(2L, 3L, 4L, 5L, 3L, 4L, 5L), n = c(1L, 26L, 64L, 25L, 
13L, 33L, 36L)), class = "data.frame", row.names = c(NA, -7L)), 
    AA1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
    2L, 2L), AA1 = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 5L), n = c(31L, 
    44L, 30L, 11L, 28L, 30L, 15L, 8L, 1L)), class = "data.frame", row.names = c(NA, 
    -9L)), FNB1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 2L, 
    2L, 2L, 2L, 2L), FNB1 = c(2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 
    5L), n = c(16L, 12L, 68L, 20L, 1L, 2L, 9L, 35L, 35L)), class = "data.frame", row.names = c(NA, 
    -9L)), RE1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 1L, 
    2L, 2L, 2L, 2L, 2L), RE1 = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 
    3L, 4L, 5L), n = c(24L, 58L, 26L, 7L, 1L, 24L, 29L, 23L, 
    5L, 1L)), class = "data.frame", row.names = c(NA, -10L)))

EDIT:

Non-shiny "solution"

I created a new header as follows:

## My header {.tabset .tabset-dropdown}

Then created ggplots in a list.

```{r}
plots <- vars %>% 
  map(., ~freqsByAge %>% 
  pluck(., .x) %>% 
  ggplot(aes(x = !!sym(.x), y = n, fill = n)) +
  geom_col() +
  facet_wrap(~AGE)
...
```

Now we can call the list using

### myPlot1
```{r, echo = FALSE}
plots[[1]]
```

### myPlot2
```{r, echo = FALSE}
plots[[2]]
```

Since we set the {.tabset .tabset-dropdown} previously, all sub-headers will be accessed through a dropdown. The user can now just select the plot that they want to show.

1 Answers

You could use shiny runtime which allows to create a selectInput and to react to changes to this input with renderPlot:

---
title: "title"
author: Name
date: "`r format(Sys.time(), '%d %B, %Y')`"
output: 
 html_document:
   theme: flatly # default, cerulean, journal, flatly, darkly, readable, spacelab, united, cosmo, lumen, paper, sandstone, simplex, and yeti
   highlight: tango # default, tango, pygments, kate, monochrome, espresso, zenburn, haddock, breezedark, and textmate
   smart: true
   toc: true
   toc_depth: 2
   toc_float:
     collapsed: false
     smooth_scroll: false
   numbers_sections: true
   fig_width: 7
   fig_height: 6
   fig_caption: true
   df_print: paged
   code_folding: hide

runtime: shiny   
   
#bibliography: bibliography.bib
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
set.seed(1234)
library(knitr)
library(kableExtra)
library(ggplot2)
library(dplyr)
library(purrr)
freqsByYear <- list(LG1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 2L, 2L, 2L
), LG1 = c(2L, 3L, 4L, 5L, 3L, 4L, 5L), n = c(1L, 26L, 64L, 25L, 
13L, 33L, 36L)), class = "data.frame", row.names = c(NA, -7L)), 
    AA1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
    2L, 2L), AA1 = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 5L), n = c(31L, 
    44L, 30L, 11L, 28L, 30L, 15L, 8L, 1L)), class = "data.frame", row.names = c(NA, 
    -9L)), FNB1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 2L, 
    2L, 2L, 2L, 2L), FNB1 = c(2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 
    5L), n = c(16L, 12L, 68L, 20L, 1L, 2L, 9L, 35L, 35L)), class = "data.frame", row.names = c(NA, 
    -9L)), RE1 = structure(list(YEAR = c(1L, 1L, 1L, 1L, 1L, 
    2L, 2L, 2L, 2L, 2L), RE1 = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 
    3L, 4L, 5L), n = c(24L, 58L, 26L, 7L, 1L, 24L, 29L, 23L, 
    5L, 1L)), class = "data.frame", row.names = c(NA, -10L)))
```
```{r}
selectInput("selector",label = "Selector",
      choices = names(freqsByYear),
      selected = 1)

renderPlot(freqsByYear %>% 
  pluck(., input$selector) %>% 
  ggplot(aes(x = !!sym(input$selector), y = n, fill = n)) +
  geom_col() +
  facet_wrap(~YEAR))
```

enter image description here

Related