R shiny switch doesn't find column, when uploading file. Unless that file was created simultaneously

Sorry for the bad title description. Tried posting the same on reddit and stackoverflow but haven't gotten any help. Try running the code firs without the ## and then with them and you'll see my problem. Been asking more senior coders to have a look at it, but no solutions have been found. My conclusion is that it's a bug. Because the code works when you first create the file (no ##) then upload it but it doesn't work when you only upload it.

If I run this code, we get the Error: object 'AB' not found. But if we remove the ## from the code (recreating the file before uploading it) this problem doesn't occur. Also tableOutput finds the file (and prints it just fine) and if we call the column name instead of tab_input1() there's no issues with plotting the file. I've also made sure that the file is saved to my computer and I've tried writing it as a csv and tsv file.

library(shiny)
library(tidyverse)
library(plotly)

ui <- fluidPage(tabsetPanel(
  tabPanel("Experiment 1",
           verticalLayout(fluidRow(
             column(4, selectInput(inputId = "y_axis1", label = "Y-axis",
                         choices = c("a or", "b")))
           ),
             plotlyOutput("experiment1_plot"),
           tableOutput("table_example")
           )
  )
)
)


server <- function(input, output, session) {
  
  ##AB <- c(1, 3, 5)
  ##B <- c(2, 4, 6)
  ##C <- c(10, 20, 30)
  ##my_df <- data.frame(AB, B, C)
  ##saveRDS(my_df, "data/test.rds")
  testing_df <- readRDS("data/test.rds")
  
  tab_input1 <- reactive({
    switch(input$y_axis1,
           "a or" = AB,
           "b" = B)
  })
  
  output$table_example <- renderTable(testing_df$AB)
  
  output$experiment1_plot <- renderPlotly({
    ggplotly(
      ggplot(testing_df) +
        geom_point(aes(x = tab_input1(), y = C)) +
        ####geom_point(aes(x = testing_df[,tab_input1()], y = C)) + 
        expand_limits(x=0, y=0)
    )
  })
  
}

shinyApp(ui, server)

Tried adapting the suggestion I got at stackoverflow (the row with ####), but I think this has the exact same problem and it gives "Warning: Error in [.data.frame: undefined columns selected"

What I'm having a hard time wrapping my head around why doesn't the same error occur if I write the file inside the server. (by removing the ## signs, if you want to try it yourself)

I'm thinking the problem is caused within the switch somewhere when combined with reading the file.

Session info:

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] plotly_4.9.0    forcats_0.4.0   stringr_1.4.0   dplyr_0.8.3     purrr_0.3.2     readr_1.3.1     tidyr_0.8.3     tibble_2.1.3   
 [9] ggplot2_3.2.0   tidyverse_1.2.1 shiny_1.3.2    

loaded via a namespace (and not attached):
 [1] tidyselect_0.2.5  haven_2.1.1       lattice_0.20-38   colorspace_1.4-1  generics_0.0.2    vctrs_0.2.0       htmltools_0.3.6  
 [8] viridisLite_0.3.0 yaml_2.2.0        rlang_0.4.0       later_0.8.0       pillar_1.4.2      glue_1.3.1        withr_2.1.2      
[15] modelr_0.1.5      readxl_1.3.1      munsell_0.5.0     gtable_0.3.0      cellranger_1.1.0  rvest_0.3.4       htmlwidgets_1.3  
[22] labeling_0.3      crosstalk_1.0.0   httpuv_1.5.1      broom_0.5.2       Rcpp_1.0.2        xtable_1.8-4      promises_1.0.1   
[29] scales_1.0.0      backports_1.1.4   jsonlite_1.6      mime_0.7          hms_0.5.0         digest_0.6.20     stringi_1.4.3    
[36] grid_3.6.1        cli_1.1.0         tools_3.6.1       magrittr_1.5      lazyeval_0.2.2    crayon_1.3.4      pkgconfig_2.0.2  
[43] zeallot_0.1.0     data.table_1.12.2 xml2_1.2.1        lubridate_1.7.4   assertthat_0.2.1  httr_1.4.1        rstudioapi_0.10  
[50] R6_2.4.0          nlme_3.1-140      compiler_3.6.1  

Edit: formatting

Hi, @FoolishResearcher,

Good news: this isn't a bug, just a slight misunderstanding :slightly_smiling_face:

First, I'd like to explain why the error doesn't occur when you uncomment the ## lines: as you know, these lines create the data frame and then save it to a file; however, prior to creating the data frame, the objects AB, B, and C, are all created within the scope of the server function. Therefore, the switch() call in your tab_input1 reactive expression is able to locate the objects AB and B. Thus, it is not the act of saving the data frame to the file before loading it that resolves the error, but rather the assignment of the AB and B variables that does.

The line commented out with #### is very close to resolving the error, but the switch statement must also be updated in order to completely fix it, as so:

switch(input$y_axis1,
       "a or" = "AB",
       "b" = "B")

The reason being that if you simply return AB or B, you are returning the object, and then attempting to use it to subset the data frame. However, as you have experienced, the objects AB and B do not exist if you only load the data frame from the file. Instead, by returning the name of the column in the data frame, it can be properly used to retrieve the data.

To make things a bit clearer, you can leave your renderPlotly() call unchanged (and remove the #### line) by fixing your switch() call, like so:

switch(input$y_axis1,
       "a or" = testing_df[, "AB"], 
       "b" = testing_df[, "B"])

Again, the reason you must do this is that, when you load the object from the test.rds file, you are only loading in the data frame that was saved in it (i.e. my_df; this is because saveRDS() only saves a single R object to a file), and not the variables that were used to create it. Thus, in order to get the data you want, you must extract it from the data frame.

Hope this helps clears things up a bit!

1 Like

Thank you, your explanation was excellent!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.