0

I've seen quite a few questions on StackOverflow about problems with aes mapping in Shiny, and most of these are solved with using aes_string() in people's code. These are almost exclusively to do with x/y values, though.

My issue arises when using ggbiplot for PCA, and is related to mapping coloring variables. My app lets the client upload their own file, but I ran this through with mtcars just to make sure it was a reproducible error (it is). Here's the upload code:

ui.R

library(shiny)
shinyUI(pageWithSidebar(
  headerPanel("Where the Flip are my colors?"),
  sidebarPanel(
    fileInput('file1', 'Choose CSV File',
              accept=c('text/csv',
                       'text/comma-separated-values,text/plain',
                       '.csv')),
    tags$hr(),
    checkboxInput('header', 'Header', TRUE),
    radioButtons('sep', 'Separator',c(Comma=',',Semicolon=';',Tab='\t'),','),
    selectInput("variable",label = h5("Coloring Variable"),"")
  ),
  mainPanel(
    tableOutput("inputfile"),
    plotOutput("PCA")
  )
))

server.R

library(shiny)
shinyServer(function(input, output, session) {
upData <- reactive({if(is.null(input$file1))return(NULL) 
  inFile <- input$file1
  dat <- read.csv(inFile$datapath)
  return(dat)
})
output$inputfile <- renderTable({
  upData()
})
observe({
  updateSelectInput(
    session,
    "variable",
    choices=names(upData()))
})
  output$PCA <- renderPlot({
    upData.pca <- prcomp(upData(), scale = TRUE)
    ggbiplot(upData.pca, obs.scale = 1, var.scale = 1) 
#    + geom_point(aes_string(color=input$variable))
  })
})

If I run this code as-is, it provides the uploaded dataframe and PCA biplot I want. But when I uncomment the geom_point line, I get a "invalid argument to unary operator" error. I've done this outwith Shiny, and the code runs fine with mtcars. When I run my actual code, I get an "object 'input' not found" error, so my toy example and my actual issue aren't quite the same, but I'm hoping the problem is related.

I've looked through the documentation on aes in Shiny, and scoured Google for a similar question, but haven't been able to come up with a solution. I would LOVE some help with this.


Using Gopala's code, the errors I'm seeing are:

Warning: Error in [[: subscript out of bounds Stack trace (innermost first): 84: FUN 83: lapply 82: aes_string 81: layer 80: geom_point 79: renderPlot [#17] 71: output$PCA 4: <Anonymous> 3: do.call 2: print.shiny.appobj 1: <Promise> Don't know how to automatically pick scale for object of type tbl_df/tbl/data.frame. Defaulting to continuous. Warning: Error in : Aesthetics must be either length 1 or the same as the data (32): colour, x, y Stack trace (innermost first): 71: output$PCA 4: <Anonymous> 3: do.call 2: print.shiny.appobj 1: <Promise> Warning: Error in eval: object 'drat' not found Stack trace (innermost first): 71: output$PCA 4: <Anonymous> 3: do.call 2: print.shiny.appobj 1: <Promise>

Scott
  • 311
  • 2
  • 13
  • When I return `mtcars` in place of NULL from that reactive so I can test without uploading files and such, it works fine for me. ` `packageVersion('shiny')` in my case is `[1] ‘0.12.2’` – Gopala May 08 '16 at 18:20
  • That's odd - I just did the same thing and it returned the "invalid argument to unary operator" error again. My version is 0.13.2, so now I'm all shades of confused. You're able to color the points reactively based on the input variable? – Scott May 08 '16 at 18:33
  • Yes, selecting mpg, or cyl changes the coloring and the legend.I get some parse error with subscript out of bounds, but that has not prevented anything in the app from working. Have not debugged that error yet. – Gopala May 08 '16 at 18:35

2 Answers2

0

Here is the code I am using and it works:

library(shiny)
library(ggbiplot)

ui <- pageWithSidebar(
  headerPanel("Where the Flip are my colors?"),
  sidebarPanel(
    fileInput('file1', 'Choose CSV File',
              accept=c('text/csv',
                       'text/comma-separated-values,text/plain',
                       '.csv')),
    tags$hr(),
    checkboxInput('header', 'Header', TRUE),
    radioButtons('sep', 'Separator',c(Comma=',',Semicolon=';',Tab='\t'),','),
    selectInput("variable",label = h5("Coloring Variable"),"")
  ),
  mainPanel(
    tableOutput("inputfile"),
    plotOutput("PCA")
  )
)

server <- function(input, output, session) {
  upData <- reactive({if(is.null(input$file1)) return(mtcars) 
    inFile <- input$file1
    dat <- read.csv(inFile$datapath)
    return(dat)
  })
  output$inputfile <- renderTable({
    upData()
  })
  observe({
    updateSelectInput(session,
      "variable",
      choices=names(upData()))
  })
  output$PCA <- renderPlot({
    upData.pca <- prcomp(upData(), scale = TRUE)
    ggbiplot(upData.pca, obs.scale = 1, var.scale = 1) +
      geom_point(aes_string(color=input$variable))
  })
}

shinyApp(ui = ui, server = server)
Gopala
  • 10,363
  • 7
  • 45
  • 77
  • I just ran your code, and it's a slight improvement - I'm now getting the "object not found" error (where the input variable, like cyl etc., are listed). But there's no biplot, and no color changes. I can't see how this would be a system error, as I've restarted R and checked all the dependencies. – Scott May 08 '16 at 18:57
  • Perhaps change the `selectInput` to `renderUI` and generate it on server side instead of through observe/update and see if there is a problem/bug there in your version. – Gopala May 08 '16 at 19:02
  • Switching server-side to `output$variable <- renderUI({ selectInput("variable", "Variable", choices=names(upData()) })` and ui-side to `uiOutput("variable")` yields the exact same problem as before. I'm absolutely baffled. – Scott May 08 '16 at 19:38
0

Well, I finally got it.

geom_point(aes_string(color=upData()[,input$variable]))

For whatever reason beyond my limited understanding of R, I had to define the initial reactive value upData().

Hope that helps someone else avoid a few days of agony.

Scott
  • 311
  • 2
  • 13