Search code examples
rshinyflexdashboard

When selecting multiple inputs in a shiny app, why does the error depend on the order that the inputs were selected?


I have a flexdashboard document with runtime: shiny (I posted the app here https://arie.shinyapps.io/reproducible_example/ and embedded the code, but wanted to put the code below as well in case the app exceeds its allotted usage on shinyapps.io):

--- title: "Example" runtime: shiny output: flexdashboard::flex_dashboard: source_code: embed ---

Given the following example data set:

```{r setup, include=FALSE}
library(flexdashboard)
library(tidyverse)

df <- tibble(name = c("peter", "paul", "mary"), 
         value = c(1:3))
```

I want to be able to make multiple selections from the following user interface:

Column {data-width=250, .sidebar}
-----------------------------------------------------------------------

```{r}

# creates interface
selectInput("name_input", label = "Name", choices = df$name,
        selected = NULL, multiple = TRUE, selectize = TRUE)

```

and have a ggplot "react" to the selections. So I make a reactive data set:

```{r}
# reactive data
df_reactive <- reactive(df[df$name == input$name_input,])

```

and create the following plot:

Column {data-width=750}
-----------------------------------------------------------------------

### Chart B

```{r}
renderPlot(
 ggplot(df_reactive(), aes(x = input$name_input, y = value) ) +
  geom_col()
 )
```

Now, when I Run Document and select first peter, then paul, and then mary, the plot reacts exactly as expected: It adds a bar each time a name is added. The problem occurs when I, for example, first select paul and then peter, which throws the error Aesthetics must be either length 1 or the same as the data (2): x, y.

The error makes sense to me in the context of a static chart, but I am confused about why the order of selecting the names should matter and how it can be resolved.


Solution

  • The problem is within:

    df_reactive <- reactive(df[df$name == input$name_input,])
    

    If length(input$name_input) is < 3 you will try to compare two arrays of different length. R will throw an error and it is also not the test you actually want to perform. As I see it, you want to test for each element in df$name if it is included in input$name_input. Luckily there is a shortcut for that in R, so you wont have to use a for loop or sapply(),...

    Like I wrote in the comments: df_reactive <- reactive(df[df$name %in% input$name_input,]) will work as well.

    For more details concerning the notation, i would refer to an existing answer as the answer would become more of a duplicate then. The difference between == and %in% is explained here: difference between `%in%` VS `==`