Reputation: 113
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
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