1

I am new to creating R Shiny apps. So far I'm making a part of my app where I am trying to generate different plots depending on which variable selected to analyze. I will use the built-in dataset iris as an example.

library(shiny)
library(tidyverse)

ui <- fluidPage(
  titlePanel("Title"),
  sidebarLayout(
    sidebarPanel("Create plots of mean variables by species. ",
            varSelectInput("vars", h5("Choose a variable to display."),
                data = iris,
                selected = "Sepal.Length"),
                sliderInput("toprange", h5("Display Number of Species"),
                            min = 1, max = 3, value = 3)), 
                            #in my actual dataset there are more than 30 different levels.
    mainPanel(plotOutput("bars"))

  )
)

server <- function(input, output) {
  output$bars <- renderPlot({

    species_plot(input$vars, input$toprange)

  })
}

shinyApp(ui = ui, server = server)

Here is the function used to create the plots:

species_plot <- function(variable, min) {
iris %>%
  group_by(Species) %>%
  filter(Species != "") %>% 
  summarize(avg = mean({{variable}})) %>% 
  top_n(avg, min) %>%
  ggplot(aes(x = reorder(Species, avg), y = avg)) +
  geom_col() +
  labs(x = "Species", y = paste("Mean", toString(sym(variable)))) +
  ggtitle(paste("Mean", toString(sym(variable)), "by Species")) +
  coord_flip()
}

When I run the app, the everything on the sidebar shows, but on the main panel an error "missing value where TRUE/FALSE needed" pops up, and I am not sure where this is stemming from. I don't see a conditional anywhere, for example, that would output this error.

ngander
  • 11
  • 2

1 Answers1

0

The problem is in your plotting function, not your shiny code. The approach you're using to pass a quoted variable name to filter doesn't work. See this Q&A for one that does. In your function, that looks like...

species_plot <- function(variable, min) {
iris %>%
  group_by(Species) %>%
  filter(Species != "") %>% 
  summarize(avg = mean(!!sym(variable))) %>% 
  top_n(avg, min) %>%
  ggplot(aes(x = reorder(Species, avg), y = avg)) +
  geom_col() +
  labs(x = "Species", y = paste("Mean", variable)) +
  ggtitle(paste("Mean", variable, "by Species")) +
  coord_flip()
}

Note that this also means you don't need all that toString(sym(variable)) stuff later in the function either. It's already a string, so just pass variable.

As a side note, I think top_n isn't doing what you think it's doing in that function, either. After you've run summarize, each group only has one value, so top_n throws an error message. The function works anyway because it just ignores that illogical call and moves on. But whatever it is you're trying to do there, you're going to need to do differently.

ulfelder
  • 5,305
  • 1
  • 22
  • 40