tc_data
tc_data

Reputation: 113

selecting dimensions of plot in Shiny

I'm working on a ShinyApp where I have to print out a lot of similar plots. I thought it would be an elegant solution to let the user choose the desired y-dimension of the plot via Input, so having a multitude of similar plotoutputs can be avoided. I've got this running via the following code:

library(tidyverse)
library(shiny)

set.seed(1)
name <- c("a", "b", "c")
v1 <- sample(1:100, 3)
v2 <- sample(1:100, 3)

df <- data_frame(name, v1, v2) 


ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      uiOutput("selector")
    ),
    mainPanel(
      plotOutput("plot")
    )
  )
)

server <- function(input, output){

  output$selector <- renderUI({

    selectizeInput("select", "select column:", choices = colnames(df), selected = "v1")
  })

  data <- reactive({

     df %>% 
      select(name, y = input$select)

  })

  output$plot <- renderPlot({

    ggplot(data())+
      geom_col(aes(x = name, y = y))+
      geom_hline(yintercept = mean(data()$y, na.rm = TRUE), color = "red", size = 1)

  })

}

shinyApp(ui = ui, server = server)

The code executes and the app works as desired, but I still get an error message:

Error in : input$select must resolve to integer column positions, not NULL

I assume this is due to the select command targeting both a variable name and index (via input$select).

I'm wondering if there is a cleaner or more elegant way of doing this.

Upvotes: 1

Views: 306

Answers (1)

Florian
Florian

Reputation: 25385

You could use req() for this, see the documentation of that function here. A working example is shown below.

library(ggplot2)
library(dplyr)
library(shiny)

set.seed(1)
name <- c("a", "b", "c")
v1 <- sample(1:100, 3)
v2 <- sample(1:100, 3)

df <- data_frame(name, v1, v2) 


ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      uiOutput("selector")
    ),
    mainPanel(
      plotOutput("plot")
    )
  )
)

server <- function(input, output){

  output$selector <- renderUI({

    selectizeInput("select", "select column:", choices = colnames(df), selected = "v1")
  })

  data <- reactive({

    req(input$select)

    df %>% 
      select(name, y = input$select)

  })

  output$plot <- renderPlot({
    ggplot(data())+
      geom_col(aes(x = name, y = y))+
      geom_hline(yintercept = mean(data()$y, na.rm = TRUE), color = "red", size = 1)

  })

}

shinyApp(ui = ui, server = server)

Alternatively, you could simply create your input in the UI, but that may not be possible depending on your application:

library(ggplot2)
library(dplyr)
library(shiny)

set.seed(1)
name <- c("a", "b", "c")
v1 <- sample(1:100, 3)
v2 <- sample(1:100, 3)

df <- data_frame(name, v1, v2) 


ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectizeInput("select", "select column:", choices = colnames(df), selected = "v1")
    ),
    mainPanel(
      plotOutput("plot")
    )
  )
)

server <- function(input, output){

  data <- reactive({

    df %>% 
      select(name, y = input$select)

  })

  output$plot <- renderPlot({
    ggplot(data())+
      geom_col(aes(x = name, y = y))+
      geom_hline(yintercept = mean(data()$y, na.rm = TRUE), color = "red", size = 1)

  })

}

shinyApp(ui = ui, server = server)

Hope this helps!

Upvotes: 2

Related Questions