Kevin_Nguyen
Kevin_Nguyen

Reputation: 112

Shiny if else statement

I am having problems using conditional statements in Shiny. I want the user select number of variable. If choose 1 variable then plot chart of 1 variable (ex density plot), if choose 2 variable then plot chart of 2 variables (ex scatter plot). I have tried a few ways, but the output is not as my expected. How can i use if else statement in Shiny server? Tks

UI

   df <- mtcars
    ui <- fluidPage(
        h1("My first app",
           style = 'color: green;
           font-style: italic'),
        hr(),
        fluidRow(
            sidebarPanel(
                radioButtons(inputId = "number",
                             label = "Select number of variable",
                             choices = c("1 variable" = 1,
                                         "2 variable" = 2)),
                selectInput(inputId = "x",
                            label = "Variable 1",
                            choices = names(df)),
                conditionalPanel(
                    condition = "input.number == 2",
                    selectInput(inputId = "y",
                                label = "Variable 2",
                                choices = names(df))
                    ) 
                ),
            column(8, plotOutput("plot"))
        ),
        hr(),
        plotOutput("plot") )

Server

server <- function(input, output, session){
    observeEvent(input$x, 
                 {updateSelectInput(session,
                                    inputId = "y",
                                    label = "Variable 2",
                                    choices = names(df)[names(df) != input$x])
                 })
    
    data <- reactive({
        if(input$number == 1){
            data <- df %>% 
                select(input$x)
        } else {
            data <- df %>% 
                select(input$x, input$y)
        }
    })
    
    output$plot <- renderPlot({
        if(input$number == 1){
            ggplot(data = data(),
                   x = get(input$x))+
                geom_density()
        } else {
            ggplot(data = data,
                   x = get(input$x),
                   y = get(input$y)) +
                geom_point()
        }
    })
}

shinyApp(ui = ui, server = server)

Upvotes: 3

Views: 1398

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388982

You can try the following code -

  • plotOutput("plot") was mentioned twice, removed it to include it only once.
  • We don't need to check for conditions while creating the dataset in reactive, handle it in the plot code itself.
  • Use .data to refer column names in ggplot code.
library(shiny)
library(ggplot2)

df <- mtcars
ui <- fluidPage(
  h1("My first app",
     style = 'color: green;
           font-style: italic'),
  hr(),
  fluidRow(
    sidebarPanel(
      radioButtons(inputId = "number",
                   label = "Select number of variable",
                   choices = c("1 variable" = 1,
                               "2 variable" = 2)),
      selectInput(inputId = "x",
                  label = "Variable 1",
                  choices = names(df)),
      conditionalPanel(
        condition = "input.number == 2",
        selectInput(inputId = "y",
                    label = "Variable 2",
                    choices = names(df))
      ) 
    ),
    column(8, plotOutput("plot"))
  )
)


server <- function(input, output, session){
  
  data <- reactive({
    df
  })

 observeEvent(input$x, 
               {updateSelectInput(session,
                                  inputId = "y",
                                  label = "Variable 2",
                                  choices = names(df)[names(df) != input$x])
               })
  
  output$plot <- renderPlot({
    
    if(input$number == 1){
      plot <- ggplot(data = data(), aes(x = .data[[input$x]])) + geom_density()
    } else {
      plot <- ggplot(data = data(),
             aes(x = .data[[input$x]], y = .data[[input$y]])) +
        geom_point()
    }
    plot
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 3

Waldi
Waldi

Reputation: 41220

You could use aes_string.
Another very important point is never to use the same output twice in UI:

df <- mtcars
library(ggplot2)
library(dplyr)

ui <- fluidPage(
  h1("My first app",
     style = 'color: green;
           font-style: italic'),
  hr(),
  fluidRow(
    sidebarPanel(
      radioButtons(inputId = "number",
                   label = "Select number of variable",
                   choices = c("1 variable" = 1,
                               "2 variable" = 2)),
      selectInput(inputId = "x",
                  label = "Variable 1",
                  choices = names(df)),
      conditionalPanel(
        condition = "input.number == 2",
        selectInput(inputId = "y",
                    label = "Variable 2",
                    choices = names(df))
      ) 
    ),
    column(8, plotOutput("plot"))
  ),
  hr() 
  # Never use output twice : the UI won't work!
  #plotOutput("plot") 
  )

server <- function(input, output, session){
  observeEvent(input$x, 
               {updateSelectInput(session,
                                  inputId = "y",
                                  label = "Variable 2",
                                  choices = names(df)[names(df) != input$x])
               })
  
  data <- reactive({
    if(input$number == 1){
      data <- df %>% 
        select(input$x)
    } else {
      data <- df %>% 
        select(input$x, input$y)
    }
  })
  
  output$plot <- renderPlot({
    cat(input$x)
    if(input$number == 1){
      ggplot(data = data())+
        geom_density(aes_string(x=input$x))
    } else {
      ggplot(data = data()) +
        geom_point(aes_string(x=input$x,y=input$y))
    }
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 3

Related Questions