Search code examples
rggplot2shinypcaggbiplot

Problems with Shiny PCA and ggbiplot coloring


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>


Solution

  • 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.