1

I am creating two interactive plots in R Shiny and while I can get one plot to show up and work, the second plot keeps giving me the "Warning: Error in [.data.frame: undefined columns selected" and will not appear.

I have looked at many solutions online and none so far have been able to help me or fix my issue.

I am having a hard time seeing how my columns are undefined, but I am also relatively new to R Shiny and could be easily overlooking something, so I was hoping someone could help me figure this out.

Here is my code:

library(shiny)
library(dplyr)
library(readr)
library(ggplot2)
library(tidyverse)

age <- c(1, 4, 7,10, 15)
v_m_1 <- c(10, 14, 17, 20, 25)
v_m_2 <- c(9, 13, 16, 19, 24)
sex <- c("F", "M","U", "F", "M")
P_v_rn <- c(0.11, 0.51, 0.61, 0.91, 1)
C_v_rn <- c(11.1, 15.1, 16.1, 19.1, 20.1)
P_v_rk <- c(0.11, 0.51, 0.61, 0.91, 1)
B_v_rk <- c("Low", "Medium", "Medium", "High", "High")

df_test <- data.frame(age, v_m_1, v_m_2, sex, P_v_rn, C_v_rn, P_v_rk, B_v_rk)


# Define UI for application that draws a histogram
ui <- fluidPage(
  
  # Application title
  titlePanel("Test"),
  
  # Sidebar with a slider input for number of bins 
  verticalLayout(
    sidebarLayout(
      sidebarPanel(
        selectInput(inputId = "xvar",
                    label = "Choose X variable", #All variables are numeric
                    c("Age" = 1),
                    selected = 1),
        selectInput(inputId = "yvar",
                    label = "Choose bone variable", #All variables are numeric
                    c("v_m_1" = 2,
                      "v_m_2" = 3),
                    selected = 2),
        checkboxInput(inputId =  "regression", 
                      label = "Fit LOESS - By Sex",
                      value = FALSE)),
      mainPanel(
        plotOutput('dataplot1')
      )
    ),
    
    tags$hr(),
    
    sidebarLayout(
      sidebarPanel(
        selectInput(inputId = "xvar_name",
                    label = "Choose X variable", #All variables are numeric
                    c("Age" = 1),
                    selected = 1),
        selectInput(inputId = "yvar_name",
                    label = "Choose Y variable", #The first variable option is numeric, the rest are factors
                    c("P_v_rk" = 7,
                      "B_v_rk" = 8),
                    selected = 7),
        selectInput(inputId = "zvar_name",
                    label = "Choose Z variable", #All variables are numeric
                    c("C_v_rn" = 6,
                      "P_v_rn" = 5),
                    selected = 6)),
      
      # Show a plot of the generated distribution
      mainPanel(
        plotOutput('dataplot2')
      )
      
    ),
    tags$hr(),
  ))


# Define server logic required to draw a scatterplot
server <- function(input, output) {
  df <- df_test  %>% 
    select(age, v_m_1, v_m_2, sex, P_v_rn, C_v_rn, P_v_rk, B_v_rk)
  
  df$B_v_rk <- as.factor(df$B_v_rk)
  
  #Growth Curve 
  output$dataplot1 <- renderPlot({
    xvar <- as.numeric(input$xvar)
    yvar <- as.numeric(input$yvar)
    Sex <- as.factor(df$sex)
    
    p <- ggplot() + 
      aes(x = df[ ,xvar],
          y = df[ ,yvar], 
          col = sex) +
      geom_point(alpha = 0.5, aes(size = 1.5)) +  # 50% transparent
      labs(x = names(df[xvar]),
           y = names(df[yvar])) + 
      theme_classic()
    
    if(input$regression) {
      # add a line to the plot
      p <- p + geom_smooth() 
      
    }
    
    p  # The plot ('p') is the "return value" of the renderPlot function
  })
  
  #Environmental metrics
  output$dataplot2 <- renderPlot({
    xvar_name <- input$xvar_name
    yvar_name <- input$yvar_name
    zvar_name <- input$zvar_name
    
    #Color palette for ggplots as blue color range was difficult for me 
    
    fun_color_range <- colorRampPalette(c("yellow", "red"))
    
    my_colors <- fun_color_range(20) 
    
    p2 <- ggplot() +
      aes(x = df[ ,xvar_name],
          y = df[ ,yvar_name],
          col = df[ ,zvar_name]) +
      geom_point(alpha = 0.5, aes(size = 1.5)) +  # 50% transparent
      scale_colour_gradientn(colors = my_colors) + 
      labs(x = names(df[xvar_name]),
           y = names(df[yvar_name])) + 
      theme_classic() 
    
    
    p2  # The plot ('p2') is the "return value" of the renderPlot function
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Again the first plot works fine, it is the second plot that is producing an error code.

I guess I am confused as the code for the first plot works fine but it won't work for the second plot.

For reference, this is the layout I want, except I want another plot in the error code location.

enter image description here

Kat
  • 15,669
  • 3
  • 18
  • 51
  • Does this answer your question? [How to connect user input with gganimate graph in R shiny?](https://stackoverflow.com/questions/71810703/how-to-connect-user-input-with-gganimate-graph-in-r-shiny) – Limey Nov 11 '22 at 07:13
  • `xvar_name <- as.numeric(input$xvar_name)` seems suspicious, this should just be character since it is the name of the column in the dataframe – Remko Duursma Nov 11 '22 at 08:18
  • but it is difficult to tell without a reproducible example or the UI function – Remko Duursma Nov 11 '22 at 08:19
  • @RemkoDuursma I removed the as.numeric but it didn't change anything, still had the same error. – Kristen Tuosto Nov 11 '22 at 13:08
  • @Limey I tried the suggestions in the link, but still had the same error code. – Kristen Tuosto Nov 11 '22 at 13:09
  • The code in the answer I linked to *does* work. You must be doing something different. There is nothing else I can add without a minimal reproducible example ([This post](https://stackoverflow.com/help/minimal-reproducible-example) may help) showing how you have tried to implement the solution it suggests. – Limey Nov 11 '22 at 13:14
  • @Limey thank you for the link to the post on minimal reproducible. I think I just created one or at least I can reproduce the error code without the data I was using. – Kristen Tuosto Nov 11 '22 at 14:30
  • My guess is that you did `names(df[xvar_name])`. If df is a data frame, this will throw the given error. You either use double brackets (`df[[...]]`) or a comma (`df[ ..., ... ]`). In general, to identify the place where the problem occurs, use `browser()` in your code. – January Nov 11 '22 at 15:12
  • 1
    As @January points out, your syntax is incorrect. But you will also get an error unless you change `scale_colour_gradientn(colors = my_colors)` to something else,(or omit it all together). Change your definition of `p2` to `p2 <- df %>% ggplot(aes(x = !!{{xvar_name}}, y = !! {{yvar_name}}, col = !! {{zvar_name}})) + geom_point(alpha = 0.5, aes(size = 1.5)) + labs(x = names(df[[xvar_name]]), y = names(df[[yvar_name]])) + theme_classic() ` and you will at least get a plot. Whether it's the right plot, I cannot say... – Limey Nov 11 '22 at 15:16

1 Answers1

0

My guess is that the bug is in the line with names(df[xvar_name]). If df is a data frame, this will throw the error you quoted. To subset a data frame with indices or column names you either use double brackets (df[[...]]) or a comma (df[ ..., ... ]). I think you meant names(df[ , xvar_name ]). This error is repeated on the line below as well.

In general, to identify the place where the problem occurs, use browser() in your code.

January
  • 16,320
  • 6
  • 52
  • 74