Search code examples
rshinydata-scienceshinyapps

flip boxplot with conditional statement in Shiny app R


I am generating a boxplot in Shiny app in R based on user input, The user selects one factor variable and one numeric variable then a box blot of these variables is shown. My problem is that; some of the factor variables have more than 10 levels, the x-axis labels overlap, so I would like the boxplot to flip if the variable chosen has more than a certain number of levels so the x-axis label names can be horizontal.

I have tried using the If statement in the server section, I used the nlevels(dataset[[input$varX]])but it's not getting the number of levels for the factor variables. The plot area is blank. The nlevels(dataset[[input$varX]]) fetches the number of levels in the category,

    column1<- c("box","box","box","box","rec","rec","circle","circle","circle","circle","circle","circle","circle")
    column2<- c(1,2,3,6,8,9,10,12,15,18,11,19,20)
    column3<- c("blue","red","yellow","green","black","blue","red","yellow","green","black","red","black","yellow")
    dataset<- data.frame(column1,column2,column3)
ui <- fluidPage(theme = shinytheme("flatly"),
                navbarPage(tabPanel("Boxplot", 
                            
                           sidebarLayout(
                             sidebarPanel(
                             
                               varSelectInput("varX", "Var1:", dataset),
                               varSelectInput("varY", "Var2:", dataset)
                             ),
                             
                             # Show plot 
                             mainPanel(
                               br(),
                               plotOutput("boxPlot")
                             )
                           )
                           ),


server <- function(input, output) {
    output$boxPlot <- renderPlot({
      if(nlevels(dataset[[input$varX]]) < 4){
        plot_a<- ggplot(dataset,aes_string(x=input$varX, y=input$varY))+
          geom_boxplot()+
          ggtitle(paste("boxplot of ", input$varX, "vs", input$varY))+
          
        plot_a
      }

      if(nlevels(dataset[[input$varX]]) >= 4){
        plot_box + coord_flip()
      }
      
})
}


Solution

  • One problem you've got is that your columns aren't factors, and so there are no levels. I changed the first and third columns to factors.

    The main fix for you missing plots is that you need to create plot_a before the if statements. Then modify as needed based on your logic about the levels. Then you need to return the plot_a by putting it on its own line at the very end of the renderPlot.

    library(tidyverse)
    library(shiny)
    
    column1<- c("box","box","box","box","rec","rec","circle","circle","circle","circle","circle","circle","circle")
    column2<- c(1,2,3,6,8,9,10,12,15,18,11,19,20)
    column3<- c("blue","red","yellow","green","black","blue","red","yellow","green","black","red","black","yellow")
    dataset<- data.frame(column1 = factor(column1),column2,column3 = factor(column3))
    
    ui <- fluidPage(
      varSelectInput("varX", "Var1:", dataset),
      varSelectInput("varY", "Var2:", dataset),
      br(),
      plotOutput("boxPlot")
    )
                    
    server <- function(input, output) {
      output$boxPlot <- renderPlot({
        
        plot_a<- ggplot(dataset,aes_string(x=input$varX, y=input$varY))+
          geom_boxplot()+
          ggtitle(paste("boxplot of ", input$varX, "vs", input$varY))
        
        
        if(nlevels(dataset[[input$varX]]) >= 4){
          plot_a <- plot_a + coord_flip()
        }
        plot_a
      })
    }
    
    shinyApp(ui, server)
    

    I removed all of your navbars/tabsets because they were irrelevant to the question and squeezing everything.