Reputation: 1441
I'm trying to create a shiny app in which a user would be able to upload a .csv file, and then apply a filter on that dataframe and then make a plot using ggplot2. Unfortunately I stumbled upon a problem when trying to create a select input menu from a variable coming from the .csv that is supposed to be uploaded.
To create a simple example we can export the diamonds
dataset from ggplot2
as a .csv file:
write.csv(diamonds, "diamonds.csv")
Then to create the shiny app:
library(shiny)
library(shinyWidgets)
library(ggplot2)
ui <- fluidPage(
titlePanel("test shiny"),
# Sidebar with a slider input for number of bins
sidebarLayout(sidebarPanel(
fileInput('file1', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'text/tab-separated-values',
'text/plain',
'.csv',
'.tsv'
)
),
tags$hr(),
pickerInput(
inputId = "caratx",
label = "Choose carat",
choices = c("Select all", unique(user_data$carat)),
multiple = TRUE
),
selectInput(
inputId = "clarityx",
label = "Choose distance: ",
choices = unique(user_data$clarity)
)
),
mainPanel(plotOutput("endplot"))
))
# Define server logic
server <- function(input, output) {
output$endplot <- renderPlot({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
user_data <- read.csv(inFile$datapath, header = T,
sep = ",", quote = input$quote)
validate(
need(input$entityx, 'Please select at least one carat'),
need(input$indicatorx, 'Please select at least one clarity')
)
if (input$caratx %in% "Select all") {
user_data <- user_data %>%
filter(carat %in% input$caratx)
} else {
user_data <- user_data %>%
filter(carat %in% input$caratx) %>%
filter(clarity %in% input$clarityx)
}
user_data %>%
ggplot(aes(x = `cut`)) +
geom_point(aes(y = price), color = "red") +
geom_point(aes(y = depth), color = "blue")
})
}
# Run the application
shinyApp(ui = ui, server = server)
This is the output:
Error in unique(user_data$carat) : object 'user_data' not found
Is there a way to make this work ?
Many thanks !
Upvotes: 0
Views: 1695
Reputation: 26333
The actual question you're asking should be solved by turning user_data
into a reactive and rendering the inputs using uiOutput+renderUI, as @kwiscion correctly commented.
But unfortunately, your code has a few other errors that make it not reproducible:
diamonds
, not cars
input$quote
doesn't exist in your code, so I removed the reference to itlibrary(dplyr)
for some of the functions in your codeinput$entityx
and input$indicatorx
don't existThe above 4 errors are not related to your question, but made it much harder and longer to answer your question. In the future, please try to make sure that the code you post is correct and reproducible.
Below is an answer to your question that solved the 4 issues above and implements the two suggestions by @kwiscion
library(shiny)
library(shinyWidgets)
library(ggplot2)
library(dplyr)
ui <- fluidPage(
titlePanel("test shiny"),
# Sidebar with a slider input for number of bins
sidebarLayout(sidebarPanel(
fileInput('file1', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'text/tab-separated-values',
'text/plain',
'.csv',
'.tsv'
)
),
tags$hr(),
uiOutput("caratx_input"),
uiOutput("clarityx_input")
),
mainPanel(plotOutput("endplot"))
))
# Define server logic
server <- function(input, output) {
file_data <- reactive({
req(input$file1)
read.csv(input$file1$datapath, header = TRUE,
sep = ",")
})
output$caratx_input <- renderUI({
req(file_data())
pickerInput(
inputId = "caratx",
label = "Choose carat",
choices = c("Select all", unique(file_data()$carat)),
multiple = TRUE
)
})
output$clarityx_input <- renderUI({
req(file_data())
selectInput(
inputId = "clarityx",
label = "Choose distance: ",
choices = unique(file_data()$clarity)
)
})
output$endplot <- renderPlot({
req(file_data())
validate(
need(input$caratx, 'Please select at least one carat'),
need(input$clarityx, 'Please select at least one clarity')
)
user_data <- file_data()
if (input$caratx %in% "Select all") {
user_data <- user_data %>%
filter(carat %in% input$caratx)
} else {
user_data <- user_data %>%
filter(carat %in% input$caratx) %>%
filter(clarity %in% input$clarityx)
}
user_data %>%
ggplot(aes(x = `cut`)) +
geom_point(aes(y = price), color = "red") +
geom_point(aes(y = depth), color = "blue")
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upvotes: 5
Reputation: 596
You need to
pickerInput
with renderUI
(https://shiny.rstudio.com/articles/dynamic-ui.html).(Full code below)
user_data
) you have to make it reactive expression by putting the calculation inside reactive({ })
. Then you can refer to the value like to a function, i.e. user_data()
. So in your case it would be:user_data <- reactive({
read.csv(input$file1$datapath, header = T,
sep = ",", quote = input$quote)
})
user_data() %>% ...
Also, it has to be pulled out fromrenderPlot()
to work as reactive.
renderUI()
:ui.R
...
uiOutput('caratxui'),
...
server.R
...
output$caratxui <- renderUI({
pickerInput(
inputId = "caratx",
label = "Choose carat",
choices = c("Select all", unique(user_data()$carat)),
multiple = TRUE
)
})
...
Full code:
library(shiny)
library(shinyWidgets)
library(ggplot2)
ui <- fluidPage(
titlePanel("test shiny"),
# Sidebar with a slider input for number of bins
sidebarLayout(sidebarPanel(
fileInput('file1', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'text/tab-separated-values',
'text/plain',
'.csv',
'.tsv'
)
),
tags$hr(),
uiOutput('caratxui'),
selectInput(
inputId = "clarityx",
label = "Choose distance: ",
choices = unique(user_data$clarity)
)
),
mainPanel(plotOutput("endplot"))
))
# Define server logic
server <- function(input, output) {
user_data <- reactive({
read.csv(input$file1$datapath, header = T,
sep = ",", quote = input$quote)
})
output$caratxui <- renderUI({
pickerInput(
inputId = "caratx",
label = "Choose carat",
choices = c("Select all", unique(user_data()$carat)),
multiple = TRUE
)
})
output$endplot <- renderPlot({
validate(
need(input$entityx, 'Please select at least one carat'),
need(input$indicatorx, 'Please select at least one clarity')
)
user_data() %>%
filter(carat %in% input$caratx) %>%
filter(clarity %in% input$clarityx |
input$caratx == "Select all") %>%
ggplot(aes(x = `cut`)) +
geom_point(aes(y = price), color = "red") +
geom_point(aes(y = depth), color = "blue")
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upvotes: 2