renderPlot() error: Aesthetics must be either length 1 or the same as the data (4): x, ymin, ymax


#1

Hi!

I would like to show a plot on my shinyApp. I had it working, but had to make some adjustments to the function that creates the actual ggplot. The function works perfectly well by itself in a separate script, but throws an error when called by renderPlot.

In the shiny app the call is:

output$plot <- renderPlot(generatePlot(completeOutputTable))

The error is:

Warning: Error in : Aesthetics must be either length 1 or the same as the data (4): x, ymin, ymax
Stack trace (innermost first):
    107: check_aesthetics
    106: f
    105: l$compute_aesthetics
    104: f
    103: by_layer
    102: ggplot2::ggplot_build
    101: print.ggplot
    100: print
     89: <reactive:plotObj>
     78: plotObj
     77: origRenderFunc
     76: output$plot
      1: runApp
Warning: Error in : Aesthetics must be either length 1 or the same as the data (4): x, ymin, ymax
Stack trace (innermost first):
    80: <Anonymous>
    79: stop
    78: plotObj
    77: origRenderFunc
    76: output$plot
     1: runApp

The code for generatePlot is:

generatePlot <- function(table){
  print("in generate plot")
  

  titleName <- paste("LOR Comparison")

  aesthetics <- aes(
    x=table$id,
    y=table$`Confidence Interval (95%)`,
    ymin=table$lb,
    ymax=table$ub,
    color=table$`Comparator Drug`
    ) 
  

  plotTheme <- theme(axis.text.x = element_text(angle =0, vjust = 1,size =14,
                                                hjust = 0.5),
                     legend.text=element_text(size=12),
                     legend.position = "bottom",
                     panel.background = element_rect(fill = 'grey',color='black'),
                     plot.title = element_text(size = 12, hjust = 0.5),
                     aspect.ratio=0.7)
  

  lorPlot <- ggplot(table, aesthetics) +
    geom_pointrange(size=1,shape=4,stroke=2) +
    geom_hline(yintercept = 0,size=1) +
    ggtitle(titleName) +
    plotTheme  +
    coord_flip() +
    scale_y_continuous(limits = c(-2,6), breaks=seq(-2,6, by=1)) +
    scale_x_continuous(labels = paste(table$`Investigatory Drug`, 
                                      table$`Invest. Dose (mg)`, 
                                      "mg")) +
    labs(x = "Investigatory Dose", y = "Investigatory LOR vs Comparator") +
    labs(color = "Comparator drugs:") # the label for color
  
  return(lorPlot)
  
}

I would like to understand what the difference is between calling the function on its own in a separate script and what goes wrong when I am incorporating it into the shinyApp.

Thanks for helping.


#2

I must admit that the error message does not make a lot of sense, but here’s one suggestion:
renderPlot takes an expression as first paramter, not a result. You need to put curly brackets around it:
output$plot <- renderplot({generatePlot(completeOutputTable)})
Maybe shiny thinks generatePlot is the reactive expression, and this does not take any parameters. Thus completeOutputTable is not passed to generatePlot. Or something.


#3

Thanks a lot for responding and helping out stkrog.
Unfortunately, the error remains.

I have used the syntax renderPlot(generatePlot(completeOutputTale)) before and it worked, so that should not be the problem ironically enough. I only have the problem since generatePlot() has changed.
I am wondering if it has to do with my aes() function? If I change it to aes_string(), the error becomes

Warning: Error in : geom_pointrange requires the following missing aesthetics: x
Stack trace (innermost first):
    107: check_required_aesthetics
    106: f
    105: l$compute_geom_1
    104: f
    103: by_layer
    102: ggplot2::ggplot_build
    101: print.ggplot
    100: print
     89: <reactive:plotObj>
     78: plotObj
     77: origRenderFunc
     76: output$plot
      1: runApp

making me wonder if the root of the problem lies in how I specify x,y, etc? The forum post doesn’t show it, but the assignment of y and color contain single quotation marks around the words Confidence Interval (95%) and Comparator Drug, respectively.

But what does the original error mean anyway? That Aesthetics must be length 1 or same as the data?


#4

I would be very surprised if renderPlot worked without the curly brackets! Did you try to put in the brackets?

Anyway, please make a reprex so I can reproduce the error.


#5

If you use aes_string the fields should be in quotes:
aestethics = aes(x="id", y="Confidence Interval (95%)" ....)
But I have never seen aes used this way before, I always put it in the calls to ggplot or geom_xxx:
ggplot(table, aes_string(x="id", y="Confidence Interval (95%)", ...)
I think I remember that aes_string has had some issues in the past, so I would recommend using aes whenever possible. But due to it’s non-standard evaluation you cannot use column names like “Confidence Interval (95%)” in aes.


#6

I have tried the brackets, yes. It works without curly brackets because it is part of an observeEvent(). Upon clicking the button, a series of functions are called from external scripts and in the end, renderPlot() is called to show a plot.

I have found another error and realised that R’s global environment may have caused me to overlook where the problem lies. I will get back to you on this asap. For now though, thank you for your input.


#7

I have resolved it stkrog.

Basically, the error message made me double check the length of all input for x,y etc and I realised that one of the variables was indeed length 0. The error was not present in my separate, working script because only when running the app, will one of the parameters temporarily be set to 0.

Thank you, for helping out; it works now. :slight_smile: