1

Background: This is an odd one. Essentially, am working on a shiny app where people can pull a csv export off a particular website, upload it and then interactive with it. Because the numbers are large (millions) it defaults to scientific notation, which isn't easy on the eye, so I'm trying to use "labels = comma" to correct this.

Issue: When I have both scale_x_cont and scale_y_cont in the ggplot function, the app crashes. When I have just x or just y in there, it runs fine.

Now I tried to write the smallest reproducible piece of code I could, but when I made a simple one using mtcars and the same selectInput method, it ran fine, with no errors with both scale_x_cont and scale_y_cont in place...

Error

Error in eval(substitute(expr), envir, enclos) : geom_point requires the following missing aesthetics: x, y Error: geom_point requires the following missing aesthetics: x, y

Minimal CSV to replicate with

https://raw.githubusercontent.com/nzcoops/datasets/master/dump_test

App

require(shiny)
require(DT)
require(ggplot2)
require(scales)
runApp(
  list(
    ui = fluidPage(
      sidebarPanel(fileInput('file1', 'Choose CSV File',
                             accept=c('text/csv', 
                                      'text/comma-separated-values,text/plain', 
                                      '.csv')),
                   htmlOutput("contents2"),
                   htmlOutput("contents3")
      ),
      mainPanel(
        plotOutput("plot1"),
        dataTableOutput("contents4")
      )
    ),

    server = function(input, output, session) {

      contents1 <- reactive({
        inFile <- input$file1
        if (is.null(inFile))
          return(NULL)
        dat <<- read.csv(inFile$datapath)
        dat[,2:5] <<- lapply(dat[,2:5],function(x){as.numeric(gsub(",", "", x))})
        names(dat)
      })

      output$contents2 <- renderUI({
        if (is.null(input$file1))
          return(NULL)
        selectInput('columnsx', 'Columns X', contents1()[3:5])
      })

      output$contents3 <- renderUI({
        if (is.null(input$file1))
          return(NULL)
        selectInput('columnsy', 'Columns Y', contents1()[3:5])
      })

      output$contents4 <- renderDataTable({
        if (is.null(input$file1))
          return(NULL)
        dat
      }, options = list(paging = FALSE, searching = FALSE))

      output$plot1 <- renderPlot({
        if (is.null(input$file1))
          return(NULL)
        p <- ggplot(dat, aes_string(x=input$columnsx, y=input$columnsy)) +
          geom_point() + 
          scale_x_continuous(labels = comma) #+ scale_y_continuous(labels = comma)
        # Remove the above hash and the presence of scale_y_ will crash app
        print(p)
      })
    }
  ))
nzcoops
  • 9,132
  • 8
  • 41
  • 52
  • 1
    Does just the ggplot code work, outside of shiny but with the troublesome data? – tegancp Jun 19 '15 at 01:06
  • @tegancp yup it does, I did some testing of this given I though it could have been the 'aes_string' part that was causing the issue. – nzcoops Jun 19 '15 at 02:12

1 Answers1

1

You have some funky scoping stuff going on in the function. If you replace the first line of your function with this:

p <- ggplot(dat, aes_string(x=dat[input$columnsx], y=dat[input$columnsy]))

It will plot out ok.

jeremycg
  • 24,657
  • 5
  • 63
  • 74
  • Thanks @jeremycg. Can you explain the scoping or can you spot the obvious error? I'm surprised it is a scoping issue given it works fine when only one of scale_x or scale_y is present? One issue with your solution (which I can confirm works) is that you then don't get the right names on the axis, you get hideous long vectors, which, granted, can be fixed by adding labs(x=input$columnsx). Hmmm. – nzcoops Jun 19 '15 at 02:15
  • I really don't see why it isn't working - ggplot does some weird scoping stuff inside functions - see eg - http://stackoverflow.com/questions/10659133/local-variables-within-aes. I'm guessing the way aes_string is interpreting the input$columnx is causing the problem. – jeremycg Jun 19 '15 at 02:18