Problem with reactive geom_boxplot in shiny

Advertisements

I am trying to create a simple Shiny app that creates a mutable boxplot using ggplot. The original plot shown will include all groups, sorted by ascending mean of the variable chosen, with the first variable originally chosen as default. Sample code that simply replicates issue with similar data:
library(tidyverse)
library(shiny)

## sample data ----
sample_df <- data.frame(var_1 = sample(1:20, 100, replace = TRUE), 
                        var_2 = sample(5:25, 100, replace = TRUE), 
                        var_3 = sample(1:15, 100, replace = TRUE), 
                        var_4 = sample(25:40, 100, replace = TRUE), 
                        group_name = rep(c('A', 'B', 'C', 'D'), 25))

## defined ui layout ----
ui <- fluidPage(titlePanel("Title"),
                sidebarLayout(
                  sidebarPanel(
                    checkboxGroupInput('group_choice', 'Choose Group', choices = list('Group A' = 'A', 
                                                                                      'Group B' = 'B', 
                                                                                      'Group C' = 'C', 
                                                                                      'Group D' = 'D'), 
                                       selected = c('A', 'B', 'C', 'D')), 
                    radioButtons('variable_choice', 'Variable for Boxplot', choiceNames = c('var_1', 'var_2', 'var_3', 'var_4'), 
                                 inline = TRUE, choiceValues = c('var_1', 'var_2', 'var_3', 'var_4'), selected = 'var_1')
                  ),
                  mainPanel(
                    tabsetPanel(type = 'tabs', 
                                tabPanel('Explore Variables', plotOutput('variable_boxplot')))
                    
                  )
                )
)

# Defined server logic ----
server <- function(input, output) {
  output$variable_boxplot <- renderPlot({
    sample_sub <- sample_df %>% dplyr::select(c(group_name, input$variable_choice)) %>% filter(group_name %in% input$group_choice)
    
    ggplot(sample_sub, aes(reorder(group_name, input$variable_choice), input$variable_choice, color = group_name)) +
      geom_boxplot() + geom_jitter(width = 0.2) + 
      theme(legend.position = 'none') + labs(x = 'Group Name', y = 'Variable')
  })
}

shinyApp(ui, server)

I get the following error:

Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON.
Warning: Error in geom_boxplot: Problem while computing aesthetics.
ℹ Error occurred in the 1st layer.
Caused by error in `tapply()`:
! arguments must have same length

How can I fix this?

I created a plot outside of shiny that works (obviously with no interactivity) but it fails inside the structure

>Solution :

The issue is that input$variable_choice is a character string. To tell ggplot2 this character string is a column in your data you have to use e.g. the .data pronou, i.e. use .data[[input$variable_choice]]. See e.g. Mastering Shiny.

library(tidyverse)
library(shiny)

## sample data ----
sample_df <- data.frame(
  var_1 = sample(1:20, 100, replace = TRUE),
  var_2 = sample(5:25, 100, replace = TRUE),
  var_3 = sample(1:15, 100, replace = TRUE),
  var_4 = sample(25:40, 100, replace = TRUE),
  group_name = rep(c("A", "B", "C", "D"), 25)
)

## defined ui layout ----
ui <- fluidPage(
  titlePanel("Title"),
  sidebarLayout(
    sidebarPanel(
      checkboxGroupInput("group_choice", "Choose Group",
        choices = list(
          "Group A" = "A",
          "Group B" = "B",
          "Group C" = "C",
          "Group D" = "D"
        ),
        selected = c("A", "B", "C", "D")
      ),
      radioButtons("variable_choice", "Variable for Boxplot",
        choiceNames = c("var_1", "var_2", "var_3", "var_4"),
        inline = TRUE,
        choiceValues = c("var_1", "var_2", "var_3", "var_4"),
        selected = "var_1"
      )
    ),
    mainPanel(
      tabsetPanel(
        type = "tabs",
        tabPanel("Explore Variables", plotOutput("variable_boxplot"))
      )
    )
  )
)

# Defined server logic ----
server <- function(input, output) {
  output$variable_boxplot <- renderPlot({
    sample_sub <- sample_df %>%
      dplyr::select(c(group_name, input$variable_choice)) %>%
      filter(group_name %in% input$group_choice)

    ggplot(sample_sub, aes(
      reorder(group_name, .data[[input$variable_choice]]),
      .data[[input$variable_choice]],
      color = group_name
    )) +
      geom_boxplot() +
      geom_jitter(width = 0.2) +
      theme(legend.position = "none") +
      labs(x = "Group Name", y = "Variable")
  })
}

shinyApp(ui, server)
#> 
#> Listening on http://127.0.0.1:8540

Leave a ReplyCancel reply