5

I have an R Shiny app which plots horsepower from the mtcars data set against a user selected x variable. I would like the user to be able to select a transformation to perform on the x-variable ahead of plotting. In the simplified example below, these transformations are the ability to square it or obtain its reciprocal. I am doing this using a switch function.

While this switching function works in non-shiny contexts, I can't get it to execute inside a working shiny app. I know that I could perform the transformation on a reactive copy of the data frame and plot from that, but if possible, I would like to perform the transformation in the ggplot call itself. Does anyone have any suggestions on how to do so?

library(shiny)
library(tidyverse)

tran_func <- function(pred, trans) {
  switch(trans,
         "None" = pred,
         "Reciprocal" = 1/pred,
         "Squared" = pred^2,
  )
}

ui <- fluidPage(
  selectInput("xvar",
              "Select X Variable",
              choices = names(mtcars),
              selected = "disp"),
  selectInput("transform",
              "Select Transformation",
              choices = c("None", "Reciprocal", "Squared"),
              selected = "None"),
  plotOutput("scatter_good"),
  plotOutput("scatter_bad")
)

server <- function(input, output, session) {
  output$scatter_good <- renderPlot({
   mtcars %>% 
    ggplot(aes_string(x = "hp", y = input$xvar)) +
    geom_point()
  })
  output$scatter_bad <- renderPlot({
    mtcars %>% 
      ggplot(aes_string(x = "hp", y = tran_func(input$xvar, "Squared"))) +
      geom_point()
  })
}

shinyApp(ui, server)
DJC
  • 1,491
  • 6
  • 19

1 Answers1

4

The issue would be the evaluation of the string passed from input$xvar to modify the column. An option is to pass the 'data' also as argument in the function, and use [[ to subset the column without converting to symbol or evaluate

library(shiny)
library(ggplot2)
library(dplyr)
tran_func <- function(data, pred, trans) {
  switch(trans,
         "None" = data[[pred]],
         "Reciprocal" = 1/data[[pred]],
         "Squared" = data[[pred]]^2,
  )
}

ui <- fluidPage(
  selectInput("xvar",
              "Select X Variable",
              choices = names(mtcars),
              selected = "disp"),
  selectInput("transform",
              "Select Transformation",
              choices = c("None", "Reciprocal", "Squared"),
              selected = "None"),
  plotOutput("scatter_good"),
  plotOutput("scatter_bad")
)

server <- function(input, output, session) {
  output$scatter_good <- renderPlot({
    mtcars %>%
      mutate(y_col = tran_func(cur_data(), input$xvar, input$transform)) %>%
      ggplot(aes(x = hp, y = y_col)) +
      geom_point()
  })
  
  output$scatter_bad <- renderPlot({
    mtcars %>% 
      mutate(y_col = tran_func(cur_data(), input$xvar, input$transform)) %>%
      ggplot(aes(x = hp, y =y_col)) +
      geom_point()
  })
  
}

shinyApp(ui, server)

-output

enter image description here

akrun
  • 874,273
  • 37
  • 540
  • 662