6

I am using the following code and I always get the this subsettable error. What am I subsetting and where am I wrong. This should be some basic entry code that I modified and which did work at some point and I can't see the error.

Thank you

server.R

library(shiny)

# Define a server for the Shiny app
shinyServer(function(input, output) {

  # Filter data based on selections
  output$table <- renderDataTable({
    data <- read.table("my.csv", sep =',', header =TRUE)
    if (input$shortdesc != "All"){
      data <- data[data$ShortDescription == input$shortdesc,]
    }
    if (input$taken != "All"){
      data <- data[data$Taken == input$taken,]
    }
    if (input$location != "All"){
      data <- data[data$Location == input$location,]
    }
    data
  })

})

ui.R

library(shiny)
# Define the overall UI

shinyUI(
  fluidPage(
    titlePanel("My Items"),

    # Create a new Row in the UI for selectInputs
    fluidRow(
      column(4, 
             selectInput("man", 
                         "What:", 
                         c("All", 
                           unique(as.character(data$ShortDescription))))
      ),
      column(4, 
             selectInput("trans", 
                         "Where:", 
                         c("All", 
                           unique(as.character(data$Location))))
      ),
      column(4, 
             selectInput("cyl", 
                         "Who:", 
                         c("All", 
                           unique(as.character(data$Taken))))
      )        
    ),
    # Create a new row for the table.
    fluidRow(
      dataTableOutput(outputId="table")
    )    
  )  
)

Update:

Why does the example (see below) work and the moment I change it to my.csv it breaks ? If "data" is a buildin function wouldn't that collide also with the example below ? Sorry for not understanding, but this puzzles me.

server.R

library(shiny)

# Load the ggplot2 package which provides
# the 'mpg' dataset.
library(ggplot2)

# Define a server for the Shiny app
shinyServer(function(input, output) {

  # Filter data based on selections
  output$table <- renderDataTable({
    data <- mpg
    if (input$man != "All"){
      data <- data[data$manufacturer == input$man,]
    }
    if (input$cyl != "All"){
      data <- data[data$cyl == input$cyl,]
    }
    if (input$trans != "All"){
      data <- data[data$trans == input$trans,]
    }
    data
  })

})

ui.R.

library(shiny)

# Load the ggplot2 package which provides
# the 'mpg' dataset.
library(ggplot2)

# Define the overall UI
shinyUI(
  fluidPage(
    titlePanel("Basic DataTable"),

    # Create a new Row in the UI for selectInputs
    fluidRow(
      column(4, 
          selectInput("man", 
                      "Manufacturer:", 
                      c("All", 
                        unique(as.character(mpg$manufacturer))))
      ),
      column(4, 
          selectInput("trans", 
                      "Transmission:", 
                      c("All", 
                        unique(as.character(mpg$trans))))
      ),
      column(4, 
          selectInput("cyl", 
                      "Cylinders:", 
                      c("All", 
                        unique(as.character(mpg$cyl))))
      )        
    ),
    # Create a new row for the table.
    fluidRow(
      dataTableOutput(outputId="table")
    )    
  )  
)
digit
  • 1,513
  • 5
  • 29
  • 49
  • Can you include the full error message? There's often a hint as to the line number ... – Livius Jun 16 '14 at 09:29
  • Listening on http://127.0.0.1:4427 Error in data$ShortDescription : object of type 'closure' is not subsettable – digit Jun 16 '14 at 09:32
  • 5
    There is a function called `data` in base R. So, if R can't find a `data` object in the current environment, it assumes that you mean that function and tells you that it can't subset it. – Roland Jun 16 '14 at 09:34
  • Hmm. Not sure if I understand you. By "base R" you mean "Server.R" or do you suggest that I should not use "data" as my variable name ? Thanks for your response. – digit Jun 16 '14 at 09:38
  • "base R" refers to the package `base` or more generally all functions and packages which are automatically loaded in R. In other words, `data` also references a builtin function. – Livius Jun 16 '14 at 09:40
  • @Livius: I manipulated the same example https://stackoverflow.com/questions/51727460/multiple-drop-down-bottoms-in-shiny-as-filters-for-the-data However, I would like to plot data. How can I do it? – maniA Aug 08 '18 at 09:48
  • This is not your case, but I was getting the same error and I realized that I had a silly paranthesis mistake between my tabPanels in my ui's navbarPage, that one of the objects in them was wrongly trying to be subset. In case helps someone else, too. – FatihSarigol Apr 22 '20 at 10:46

1 Answers1

13

Expanding on @Roland 's comment: you have a namespace collision going on. There's a function data in base R, so if R can't find an object data in the current environment, the function data is referenced from the global environment. In your particular case, this happens because ui.R and server.R are in different environments, and, moreover, the individual function bodies all have their own environments. So the data in fluidRow(...) doesn't reference the datafrom output$table. You need to pass around arguments and/or dynamically construct the UI using the functions for that. See for example here.

Update for the updated question:

Replacing datawith mpg in ui.R fixes the problem because mpg is defined as a dataset in the global environment (this is a side effect of library(ggplot2)). So mpg is (almost) always accessible and has the necessary properties. For a fairer comparison, replace mpg in ui.R with data, which should bring back the old problem, because data in the global environment refers to a function and not the data frame you're trying to manipulate.

Super Update with more general solution for dynamically defining and loading selection elements for each dataset:

The server code loops through all the columns of the chosen dataframe and dynamically generates a selection box for every column that has a type other than double. (Uniqueness and equality with doubles is just asking for trouble.) This avoids the scoping issues because the UI elements are created in server.R after a call to the reactive function that loads the data.

server.R

library(shiny)
library(ggplot2)
# Define a server for the Shiny app
shinyServer(function(input, output) {

  get.data <- reactive({
    switch(input$dataset,
           "rock" = rock,
           "pressure" = pressure,
           "cars" = cars,
           "mpg" = mpg,
           "mtcars" = mtcars,
           "diamonds" = diamonds)
  })

  # Filter my.data based on selections
  output$table <- renderDataTable({
    my.data <- get.data()
    for(n in names(my.data)){
        # avoid too many cases ... 
        # unique() with double is just asking for trouble
        if(typeof(my.data[,n]) != "double"){ 
            val <- eval(parse(text=paste0("input$",n)))
            print(val)
            if(val != "All"){
                my.data <- eval(parse(text=paste0("subset(my.data,",n,"==",val,")")))
            }
        }
    }
    my.data
  })

  output$dyn.ui <- renderUI({
      my.data <- get.data()
      sel <- NULL
      for(n in names(my.data)){
          # avoid too many cases ... 
          # unique() with double is just asking for trouble
          if(typeof(my.data[,n]) != "double"){ 
              sel <- c(sel,
                   selectInput(n, n, choices=c("All",unique(my.data[,n])))
                   )
          }
      }
      sel
  })

})

ui.R

library(shiny)

# Define the overall UI

shinyUI(fluidPage(
    titlePanel("Displaying tables dynamically with renderUI() and eval()"),

    sidebarLayout(
        sidebarPanel(h2("Selection"),
                     selectInput("dataset", "Dataset", c("rock", "pressure", "cars","mtcars","diamonds")),
                     # Create a new Row in the UI for selectInputs
                     uiOutput("dyn.ui")

        )
        ,mainPanel(h2("Data"),
           dataTableOutput(outputId="table")       
        )
    )


))
Livius
  • 3,240
  • 1
  • 17
  • 28
  • I run history(Inf) and found out that I entered the following commands:Sys.getlocale() and Sys.setlocale(locale="C"). Before doing this it worked. Could this be the reason it does not work and how would I fix that ? Thanks – digit Jun 16 '14 at 09:53
  • I edited my question. It would be great if you could address that. Thank you. – digit Jun 16 '14 at 11:15
  • Thank you ! Trying to understand your code. It works that the csv is displayed. But in the sidepanel now I only get numbers and no text. I have 12 columns which are numbers and/or text. – digit Jun 17 '14 at 14:38