shinyDashboard with plotly & ggplot2 - Warning: Error in order: argument 1 is not a vector

Can one of you kind folk please help me out here - I've been tearing my hair out for a few days now!!

The below code is meant to produce an interactive plotly line chart, using ggplot formatting (no other reason than because it's relatively familiar to me), inside a shiny dashboard.

the first line chart (Australia) does not render automatically as app starts even though the start (min) and end (max) date values from the 'lf' dataset are there for it to read as defaults before any user inputs are entered. In the console and where the plot is meant to appear I receive the following warning:
Warning: Error in order: argument 1 is not a vector

Inside the app, the plot will only appear once I select a different date for the end value; changing the start date by selecting value from calendar will only cause the damn thing to spit the above warning at me again.

Questions

  1. why is it not picking up the initial start and end dates from the dataset?
  2. is it waiting for user input to kick things off by design, if so, is there a way to have it run auto on startup using the initial date range?
  3. Why does it not recognise the start date input but no problems with the end date input?
  4. what does the warning actually mean?
  5. Am I plotting this correctly? should I cut out the ggplot/plotly combo?

Thanks!!

## app.R ##
library(base)
library(dplyr)
library(raustats)
library(ggplot2)
library(lubridate)
library(shiny)
library(shinydashboard)
library(plotly)
#retrieve labour force dataset from ABS via abs.stat API
labour_force <- abs_stats(dataset = "LF", filter = list(ITEM=14, TSEST=c(20, 30)))
lf <- select(labour_force, -c(data_item, frequency, obs_status, unknown, agency_id,agency_name, dataset_name))

#change datatype of 'time' to date format 
lf$time <- paste("01", lf$time, sep = "-")
lf$time <- strptime(lf$time, format = "%d-%b-%Y")
lf$time <- as.Date(lf$time, format = "%d-%b-%Y")
str(lf)
#UI
ui <- dashboardPage(
  dashboardHeader(title = "this is a title"),
  ## Sidebar content
  dashboardSidebar(
    sidebarMenu(
      menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
      menuItem(
        dateRangeInput(
          inputId = "dateRange",
          label = "Select the date range (monthly):",
          start = min(lf$time),
          end = max(lf$time),
          min = min(lf$time),
          max = max(lf$time),
          format = "M-yyyy",
          startview = "year",
          separator = "to",
          autoclose = TRUE,
          )
      ),
      menuItem("menu item", tabName = "menuItem1", icon = icon("th")),
      menuItem("ABS website", icon = icon("th"), href = "https://abs.gov.au"),
      menuSubItem("submenu")
    )
  ),
  dashboardBody(
    tabItems(
      # First tab content
      tabItem(tabName = "dashboard",
              fluidRow(    
                box(
                  title = 'Australia',
                  status = "warning",
                  solidHeader = TRUE,
                  plotlyOutput("LFaus", height = 250),
                  width = 12
                )
              ),
              
              fluidRow(
                box(
                  title = 'Victoria',
                  status = "warning",
                  solidHeader = TRUE,
                  plotlyOutput("LFvic", height = 250),
                  width = 12
                )          
              )
      ),
      
      # Second tab content
      tabItem(tabName = "menuItem1",
              h2("welcome to menu item 1")
      )
    )
    )
)
server <- function(input, output, session) {
  
  date_range <- reactive({
    filter(lf, between(time, input$dateRange[1], input$dateRange[2]))
  })


  output$LFaus <- renderPlotly({
   LFplt_aus <- ggplot(date_range() %>% filter(adjustment_type == "Seasonally Adjusted", age == "15 and over",  region == "Australia"), aes(x= time, y= values, colour= sex)) +
      geom_line()
    ggplotly(LFplt_aus)
  })
  
  output$LFvic <- renderPlotly({
    LFplt_vic <- ggplot(data = filter(lf, adjustment_type == "Seasonally Adjusted", age == "15 and over",  region == "Victoria")) +
      geom_line(aes(time, values, colour = sex))
    ggplotly(LFplt_vic)
  })
  
}

shinyApp(ui, server)

For some reason input$dateRange is initially returning "1978-02-13" NA.
This screws up the filter and results in date_range() having zero rows.
I wonder if it's because when you set the dateRange resolution to monthly the max date is now no longer within the valid range? You could try

          min = min(lf$time)-days(31),
          max = max(lf$time)+days(31),

I rewrote the server a bit. It works once you change dateRange.
You can print diagnostics to the console when the app runs.
Also I'm not sure that you were using between properly.

server <- function(input, output, session) {
  
  date_range <- reactive({
    print(input$dateRange)
    lf %>% 
      dplyr::filter(time >= input$dateRange[1], time <= input$dateRange[2])
  })

  output$LFaus <- renderPlotly({
    print(nrow(date_range()))
    req(nrow(date_range()) > 0)
    LFplt_aus <- date_range() %>%
      dplyr::filter(adjustment_type == "Seasonally Adjusted", age == "15 and over", region == "Australia") %>%
      ggplot() +
      geom_line(mapping = aes(x = time, y = values, colour = sex))
    ggplotly(LFplt_aus)
  })

  output$LFvic <- renderPlotly({
    LFplt_vic <- lf %>% 
      dplyr::filter(adjustment_type == "Seasonally Adjusted", age == "15 and over", region == "Victoria") %>%
      ggplot() +
      geom_line(mapping = aes(x = time, y = values, colour = sex))
    ggplotly(LFplt_vic)
  })
}
1 Like

If I set the Format to include a 'day' 'month' and 'year' (d-M-yy) all the issues around max min are resolved. It is picking up 13-02-1978 because today's day of the month (as i write this) is the 13th. R has filled in the blanks with what it can pull from sys.date. A bit annoying that I can't just show month and year on the input selector but still very happy.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

thankyou so very much @woodward!! I'll implement your solution and improvements .
With the extra 31 days either side of the dates of the actual data, do you know if there are any ways to limit the user from inputting/selecting them (i.e. less than Feb1 1978 and past Mar1 2020)?