Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplotly Error in order: argument 1 is not a vector

I am trying to use ggplot2 with plotly in a shiny app in R. Following is the code I use:

# Loading the libraries ---------------
library(shiny)
library(tidyverse)
library(plotly)

# Global ----------------
if (!exists('ds', envir = .GlobalEnv, inherits = FALSE)) {
   ds <- readRDS("Analysis/Data/df_sim_updated.rds")
}

if (!exists('ado', envir = .GlobalEnv, inherits = FALSE)) {
  ado <- readRDS("Analysis/Data/df_ADOs.rds")
}

ds <- as_tibble(ds)
file_ID <- unique(ds$file.ID)
ado_Name <- c("ditiExpeon6", "VanC5", "NeonC4", "llacCadi3", "WhiteC2", 
              "Ford1", "BMWC10", "StarT7", "owT8Yell", "peC9Esca", "tarCWins13", 
              "rC11RoveLand", "F150C12", "CargoT4", "SemiT3", "RedT1", "RaceT11", 
              "BlueT5", "artTWalm9", "ghtTFrei10", "MoveT12", "WhiteT2", "ilT6Carg"
)

ado <- as_tibble(ado)


# Define UI for application --------------------
ui <- fluidPage(

   # Application title
   titlePanel("exploRing simulation"),

  # Sidebar 
   sidebarLayout(
      sidebarPanel(
        selectInput("fileid", label = h3("Select scenario"), 
                    choices = file_ID),

        selectInput("adoName", label = h3("Select ADO(s)"), 
                    multiple = TRUE, choices = ado_Name)
      ),

      # Main Panel
      mainPanel(
        uiOutput("FS"),

        plotlyOutput("plot1")

      )
   )
)

# Define server logic ---------------------------------
server <- function(input, output) {

  # Filter ds according to fileid
  data <- reactive({ds %>% filter(file.ID==input$fileid)})

  # Time Frame Slider
  output$FS <- renderUI(
    sliderInput("fs", label = h3("Time Frame"), min = min(data()$frames), 
                max = max(data()$frames), value = min(data()$frames), width = "800px")
  )

  # Position of OV at given time
  data2 <- reactive({data() %>% filter(frames==input$fs)})

  # Filter ado(s) according to fileid
  ado_data1 <- reactive(ado %>% 
                          filter(file.ID==input$fileid,
                                 ADO_name %in% input$adoName))

  # Position of ado at given time
  ado_data2 <- reactive(ado_data1() %>% 
                          filter(frames==input$fs))

  # Plot data
  output$plot1 <- renderPlotly(

  ggplotly( ggplot() +
    geom_line(data=data(),
               aes(x = x, y = y)) +
    geom_point(data = data2(),
               aes(x = x, y = y), size = 2) +
    geom_line(data = ado_data1(),
              aes(x = pos.2, y = pos.1, color = ADO_name)) +
    geom_point(data = ado_data2(),
               aes(x = pos.2, y = pos.1, color = ADO_name),
               size = 2) +
    geom_hline(yintercept = 278, linetype="longdash") +
    geom_hline(yintercept = 278-16) +
    geom_hline(yintercept = 278+16) +
      labs(x = "Longitudinal Position",
           y = "Lateral Position") +
    theme_bw())



  )





}

# Run the application ---------------------------------
shinyApp(ui = ui, server = server)

Problem

Following is the error message that I get:

> runApp('exploRe')

Listening on http://127.0.0.1:7666
Warning: Error in filter_impl: incorrect length (0), expecting: 26826
Stack trace (innermost first):
    109: <Anonymous>
    108: stop
    107: filter_impl
    106: filter_.tbl_df
    105: filter_
    104: filter
    103: function_list[[k]]
    102: withVisible
    101: freduce
    100: _fseq
     99: eval
     98: eval
     97: withVisible
     96: %>%
     95: <reactive:data2> [C:\Users\my_username\Google Drive\DrivingSimulator\exploRe/app.R#65]
     84: data2
     83: fortify
     82: layer
     81: geom_point
     80: ggplotly
     79: ggplotly
     78: func
     77: origRenderFunc
     76: output$plot1
      1: runApp
Warning: Error in order: argument 1 is not a vector
Stack trace (innermost first):
    88: order
    87: [.data.frame
    86: [
    85: to_basic.GeomLine
    84: to_basic
    83: layers2traces
    82: gg2list
    81: ggplotly.ggplot
    80: ggplotly
    79: ggplotly
    78: func
    77: origRenderFunc
    76: output$plot1
     1: runApp  

If I just use renderPlot and plotOutput, the app works fine. What am I doing wrong here?

like image 871
umair durrani Avatar asked Jun 12 '17 23:06

umair durrani


1 Answers

I can't reproduce your example, but I've encountered and solved the exact same error in my own app. The reason for this error is because Plotly is being passed a plot object that as no data in the plot object itself, but only has data associated with the additional geometry layers. This is because you haven't passed any data in the initial call of ggplot(), and there is probably something wrong (i.e. missing) with one of the important columns of the data passed to at least one of the geometries. (geom_path orders each of the axes before plotting, so it's probably x or y.)

If you run:

plot <- ggplot() +
    geom_line(data=data(),
               aes(x = x, y = y)) +
    geom_point(data = data2(),
               aes(x = x, y = y), size = 2) +
    geom_line(data = ado_data1(),
              aes(x = pos.2, y = pos.1, color = ADO_name)) +
    geom_point(data = ado_data2(),
               aes(x = pos.2, y = pos.1, color = ADO_name),
               size = 2) +
    geom_hline(yintercept = 278, linetype="longdash") +
    geom_hline(yintercept = 278-16) +
    geom_hline(yintercept = 278+16) +
      labs(x = "Longitudinal Position",
           y = "Lateral Position") +
    theme_bw())

plot$data

You will probably find an output like:

list()
attr(,"class")
[1] "waiver"

Apparently ggplot is fine with this empty object, even if there are some issues with one of the layers. It will print a warning, and just miss those points/layers which can't be plotted because a dimension is missing.

Likewise Plotly is (usually) unfussed with a malfunctioning layer, provided there's some data in the underlying plot object, the other layers will still present ok. It's the combination of an issue with the data for one of the layers, as well as there being no data in the main plot object that causes the issue with Plotly.

I suggest you try plotting each layer separately, but calling the data within ggplot(), to identify if there's an issue with one layer in particular (which I strongly suspect there is). Also, plot each object as a normal plot before passing to plotly.

i.e.:

plot <- ggplot(data = data()) +
    geom_line(aes(x = x, y = y)) 
print(plot)
ggplotly(plot)

plot <- ggplot(data = data2())+
    geom_point(aes(x = x, y = y), size = 2)
print(plot)
ggplotly(plot)

# and so on...

If you make those checks both in a test script, and inside the shiny app, I'm sure you'll isolate the problem.

I also found that trying to join the different data objects together before plotting them could also help, even crudely with bind_rows(). (Only if that's appropriate.) That way you can pass one piece of data to the ggplot() call first, and adjust the aesthetics separately for each geometry. Plotly still gets an underlying data object for the plot, which seems smooth things over, but might not reveal the real underlying issue as quickly.

like image 83
Aidan Morrison Avatar answered Sep 22 '22 14:09

Aidan Morrison