Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R shiny error when using reactive to plot

Tags:

plot

r

reactive

I have this data set:

Area <- c("Mexico", "USA", "USA", "Canada").

Type_of_participants <- c("Doctor", "Doctor", "Engineer", "Dancer".

Salary <- c("4000", "6000", "8000", "5000").

and I am trying to plot the salary base on the user input of Area(level1) and Type_of_participants(level2), but nothing appears. I modified aes to aes_string as I looked up here. Please help me find the error

My Code

`ui <- fluidPage(
   titlePanel("Survey Results"),
   sidebarLayout(
   sidebarPanel(strong("Overview Plot"),
             br(),
             ###1a.Area input
             selectInput("selection","Var",
                          choices = c("Area","Type_of_participants"),
                          selected = "Area"),
            uiOutput("choice_selection")      
),
mainPanel(    
  plotOutput("Overview"))

`server <- function(input, output) {
   output$choice_selection <- renderUI({
   checkboxGroupInput("baseinput","Detail",
                   unique(df[,input$selection])
                  )`
   })
    dt1 <- reactive({
   df %>%
    group_by(input$selection,Type) %>%
     filter (input$selection %in% input$baseinput) %>%
     summarise(avg_salary_by_area = mean(Salary, na.rm = TRUE)) %>%
     select(input$selection, Type, avg_Salary_by_area)
      })

    output$Overview <- renderPlot({
    ggplot(data= dt1())+
     aes(fill = Type)+
      geom_bar(x=input$selection, y = avg_salary_by_area,stat="identity", 
           position = position_dodge())

The result is I can select the input but can not visualize the plot. The error "unknown column Area or unknow Type of participants

Please help me find the mistake

Thank you

*** Update

Thanks to Mr Flick, I have fixed my code but it still informs error "Object area not found". Please help to advise. Thank you so much

  `dt1 <- reactive({
  df[df[,input$selection] %in% input$baseinput,] %>%
  group_by(input$selection,Type) %>%
  summarise(avg_score_by_area = mean(Score, na.rm = TRUE))
  })

 output$Overview <- renderPlot({

 ggplot(data= dt1(),aes_string(x= input$selection, 
                              y = "avg_score_by_area",fill = "Type"))+
 geom_bar(stat="identity", 
           position = position_dodge())`
like image 385
Suzie Avatar asked Sep 16 '25 14:09

Suzie


1 Answers

@Suzie - as mentioned above, it would help if you edited your question with your complete code as you currently have it.

A few things that would help:

  • Salary should be numeric in your df (or be converted with as.numeric before trying to take the mean
  • Your reactive expression can use !!as.symbol with input$selection to filter by the string name from df
  • The plot can use aes_string for the variable names.

Edit:

For further explanation of !!as.symbol, first consider what the result of input$selection. If you use browser() in your shiny code, and inspect what input$selection returns, you will see something like "Area" (it returns a string). But a string would not be appropriate in your filter - it is expecting a symbol that represents a column in your data frame. (A symbol is the name of an object like df or mtcars, etc.)

First, you want to convert a string to a symbol. You can do that either by using as.symbol() or rlang::sym(). You can try this out in your console. If you do as.symbol("df") it would return the symbol df. If you entered eval(as.symbol("df")) it would be the same as just entering df itself (and it would show the contents of your data frame).

The other issue is that tidyverse functions evaluate code expressions in a special context (searching for names within a data frame, for example). In this case dplyr knows that the name Area is in the context of df (one of the column names). This is a complicating factor since arguments are quoted. To address this, you need to unquote (replace a name with its value) with the bang-bang !! operator.

Putting both together you get !!as.symbol().

Of note, varSelectInput is a newer shiny alternative to selectInput that can be considered for use in situations like these.

For more information:

shinymeta special topics

advanced R

library(tidyverse)
library(shiny)

Area <- c("Mexico", "USA", "USA", "Canada")
Type_of_participants <- c("Doctor", "Doctor", "Engineer", "Dancer")
Salary <- c(4000, 6000, 8000, 5000)

df <- data.frame(Area, Type_of_participants, Salary)

ui <- fluidPage(
  titlePanel("Survey Results"),
  sidebarLayout(
    sidebarPanel(strong("Overview Plot"),
                 br(),
                 ###1a.Area input
                 selectInput("selection","Var",
                             choices = c("Area","Type_of_participants"),
                             selected = "Area"),
                 uiOutput("choice_selection")      
    ),
    mainPanel(    
      plotOutput("Overview")
    )
  )
)

server <- function(input, output) {

  output$choice_selection <- renderUI({
    checkboxGroupInput("baseinput", "Detail", unique(df[,input$selection]))
  })

  dt1 <- reactive({
    df %>%
      group_by(Area, Type_of_participants) %>%
      filter(!!as.symbol(input$selection) %in% input$baseinput) %>%
      summarise(avg_salary_by_area = mean(Salary, na.rm = TRUE))
  })

  output$Overview <- renderPlot({
    ggplot(data = dt1(), aes_string(x = input$selection, y = "avg_salary_by_area", fill = "Type_of_participants")) +
      geom_bar(stat="identity", position = position_dodge())
  })
}

shinyApp(ui, server)
like image 82
Ben Avatar answered Sep 18 '25 09:09

Ben