Here's a simple reproducible example of my problem.
setup
library(shiny)
library(dplyr)
original.data <- tibble(
year = seq(2000, 2020, 2),
count = rnorm(11)
)
This app works, but it gives an error.
ui <- fluidPage(
# Sidebar
sidebarLayout(
sidebarPanel(
uiOutput("year"),
),
# Show the table
mainPanel(
tableOutput("subset")
)
)
)
server <- function(input, output) {
output$year <- renderUI({
shinyWidgets::sliderTextInput(inputId = "year",
label = "Year to map",
choices = seq(2000, 2020, 2),
selected = 2020)
})
output$subset <- renderTable({
original.data[original.data$year == input$year,]
})
}
# Run the application
shinyApp(ui = ui, server = server)
But it gives this error:
Warning: Error in : Must subset rows with a valid subscript vector. ℹ Logical subscripts must match the size of the indexed input. x Input has size 11 but subscript
original.data$year == input$year
has size 0.
The error only occurs with the reactive input. If I move sliderTextInput
into the ui
, the app runs without an error.
ui <- fluidPage(
# Sidebar
sidebarLayout(
sidebarPanel(
shinyWidgets::sliderTextInput(inputId = "year",
label = "Year to map",
choices = seq(2000, 2020, 2),
selected = 2020),
),
# Show the table
mainPanel(
tableOutput("subset")
)
)
)
server <- function(input, output) {
output$subset <- renderTable({
original.data[original.data$year == input$year,]
})
}
# Run the application
shinyApp(ui = ui, server = server)
My actual use-case is a much more complicated application, where I need error-free reactive generated inputs. Does anyone see the error in my code?
CodePudding user response:
Up front, add req(input$year)
to your reactive block.
The size 0
error can occur when the app is starting up: often with larger shiny apps (lots of components/widgets and reactive blocks) and with dynamic inputs, the input widget may not be completely defined when a reactive block fires. When that happens, input$year
is not yet available, so it returns NULL
. We can reproduce it with:
tibble(mtcars)[mtcars$cyl == NULL,]
# Error: Must subset rows with a valid subscript vector.
# i Logical subscripts must match the size of the indexed input.
# x Input has size 32 but subscript `mtcars$cyl == NULL` has size 0.
Two ways to deal with this:
If you intend that the lack of
year
defined yet should mean the table is not rendered, then addreq(.)
, as inoutput$subset <- renderTable({ req(input$year) original.data[original.data$year == input$year,] })
If you think the table should be rendered but with 0 rows (similar but a little different), then you can use
%in%
instead of==
:output$subset <- renderTable({ original.data[original.data$year %in% input$year,] })