user chooses theme R shiny ggplot

Viewed 71

I want the user to be able to choose the theme for a ggplot. I am a little shaky on non-standard evaluation, but I am guessing that that is what I am missing. Any advice appreciated.

library(shiny)
library(ggplot2)
themes <- ls("package:ggplot2", pattern = "^theme_")
themes <- themes[themes != "theme_get" &
  themes != "theme_set" &
  themes != "theme_replace" &
  themes != "theme_test" &
  themes != "theme_update"]
themes <- paste0(themes, "()")
# Define UI for application that draws a histogram
ui <- fluidPage(

  # Application title
  titlePanel("Old Faithful Geyser Data"),

  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
        "Choose bin width:",
        min = 5,
        max = 15,
        value = 10
      ),
      selectInput(
        "theme",
        "choose a theme",
        themes,
        selected = "theme_minimal()",
        multiple = FALSE
      )
    ),

    # Show a plot of the generated distribution
    mainPanel(
      plotOutput("distPlot")
    )
  )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  output$distPlot <- renderPlot({
    ggplot(faithful, aes(waiting)) +
      geom_histogram(binwidth = input$bins) +
      labs(title = input$theme) +
      input$theme
  })
}

# Run the application
shinyApp(ui = ui, server = server)
#> 
#> Listening on http://127.0.0.1:6760
#> Warning: Error in ggplot_add: Can't add `input$theme` to a ggplot object.

Created on 2022-05-05 by the reprex package (v2.0.1)

2 Answers

You can use get() to get the function from its name:

server <- function(input, output) {
  output$distPlot <- renderPlot({
    ggplot(faithful, aes(waiting)) +
      geom_histogram(binwidth = input$bins) +
      labs(title = input$theme) +
      get(gsub("\\(\\)","",input$theme))()
  })

And you can avoid the gsub if you omit to add parenthesis in the theme list

I think this gives you what you want:

  output$distPlot <- renderPlot({
    ggplot(faithful, aes(waiting)) +
      geom_histogram(binwidth = input$bins) +
      labs(title = input$theme) +
      match.fun(stringr::str_sub(input$theme, 1, -3))()
  })

Explanation:

match.fun() finds a function by name. You need to drop the () from the value of input$theme. Hence the call to stringr::substr(). So match.fun(stringr::str_sub(input$theme, 1, -3)) gives you a reference to the required theme function. The final () calls it.

enter image description here

Related