Search code examples
rshinyxts

xts argument error in an R Shiny application


I am trying to visualize point data for a selected date based of a slider. However, I am having trouble with xts, as I am getting the following error:

Warning: Error in match.arg: 'arg' should be one of “years”, “quarters”, “months”, “weeks”, “days”, “hours”, “minutes”, “seconds”, “milliseconds”, “microseconds”, “ms”, “us”

How can this error be fixed?

Code

# This is a Shiny time series map web application
library(shiny)
library(tidyverse)
library(tidyr)
library(leaflet)
library(xts)



# Create sample data
Date= c("2014-04-08", "2014-06-04", "2014-04-30",
              "2014-05-30", "2014-05-01")
lat = as.numeric(c("45.53814", "45.51076", "45.43560", "45.54332",
        "45.52234"))
lon = as.numeric(c("-73.63672", "-73.61029", "-73.60100",
        "-73.56000 ", "-73.59022"))
id = as.numeric(c("1", "2", "3", "4", "5"))

# Create a df from the above columns
df = data.frame(id, lat, lon, Date)
df$Year = lubridate::year(df$Date)
df$Month = lubridate::month(df$Date, label = TRUE, abbr=FALSE)
df$Week = lubridate::week(df$Date)
df$Date = as.Date(df$Date)
ui = fluidPage(
    
    # Title
    titlePanel("Time Series Visiualization Map"),

    sidebarLayout(
        
        # Define the sidebar
        sidebarPanel(
            
            radioButtons(inputId = "Frequency",
                         label = " Select Timer Series Frequency",
                         choices = c("Week",
                                     "Month",
                                     "Year"),
                         selected = "Week",
                         inline = T),
            
            uiOutput("Time_Series_UI")
            ),
        mainPanel(
            leafletOutput("Time_Series_Map")),
    ))
    


# Define server logic required to draw a histogram
server = function(input, output) {
    
    # Render slider input depending on data frequency
    
    observe({
        # Create an xts object
        df_xts = xts(df, order.by = as.Date(df$Date))
        
        #All_Dates = unique(df$Start_Date)
        
        Filtered_Dates = df_xts[xts::endpoints(
            df_xts, on = input$Frequency)]
    
    output$Time_Series_UI = renderUI({
        sliderInput("Date", "Date:",
                    min = min(Filtered_Dates),
                    max = max(Filtered_Dates),
                    value = min(Filtered_Dates),
                    step = 1,
                    timeFormat = "%YYYY-%MM-%DD",
                    animate = T)
    })
    
    })
    
    # Filter data for the date selected
    Filtered_Data = reactive({
        req(input$Date)
        df[df$Date == input$Date]
    })
        
    
    # Create the leaflet map
    output$Time_Series_Map = renderLeaflet({
        leaflet(df) %>% 
            addTiles() %>% 
            setView(lat = 0, lng = 0, zoom = 2) 
    })
    
    # Create data markers for selected date
    observe({
        df$id = Filtered_Data()
        
        leafletProxy("Time_Series_Map", data = df) %>%
            addCircleMarkers(lng = ~lon, lat = ~lat, 
                             popup = ~id)
    })     
    
}

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

Solution

  • In order for endpoints to work, radioButtons choices need to be weeks, months and years

    I also converted the xts table into a tibble in order to get the maximum and minimum dates using slice_min and slice_max with pull.

    Finally called the reactive Filtered_Data() in the leafletProxy, (not entirely sure in this part). Now there are four points appearing during the transition of the slider.

    App:

    # This is a Shiny time series map web application
    library(shiny)
    library(tidyverse)
    library(tidyr)
    library(leaflet)
    library(xts)
    
    
    xts_to_tibble <- function(xts_obj) {
      data.frame(index(xts_obj), coredata(xts_obj)) %>%
        set_names(c("date", names(xts_obj))) %>%
        as_tibble()
    }
    
    # Create sample data
    Date <- c(
      "2014-04-08", "2014-06-04", "2014-04-30",
      "2014-05-30", "2014-05-01"
    )
    lat <- as.numeric(c(
      "45.53814", "45.51076", "45.43560", "45.54332",
      "45.52234"
    ))
    lon <- as.numeric(c(
      "-73.63672", "-73.61029", "-73.60100",
      "-73.56000 ", "-73.59022"
    ))
    id <- as.numeric(c("1", "2", "3", "4", "5"))
    
    # Create a df from the above columns
    df <- data.frame(id, lat, lon, Date)
    df$Year <- lubridate::year(df$Date)
    df$Month <- lubridate::month(df$Date, label = TRUE, abbr = FALSE)
    df$Week <- lubridate::week(df$Date)
    df$Date <- as.Date(df$Date)
    ui <- fluidPage(
    
      # Title
      titlePanel("Time Series Visiualization Map"),
      sidebarLayout(
    
        # Define the sidebar
        sidebarPanel(
          radioButtons(
            inputId = "Frequency",
            label = " Select Timer Series Frequency",
            choices = c(
              "weeks",
              "months",
              "years"
            ),
            selected = "weeks",
            inline = T
          ),
          uiOutput("Time_Series_UI")
        ),
        mainPanel(
          leafletOutput("Time_Series_Map")
        ),
      )
    )
    
    
    
    # Define server logic required to draw a histogram
    server <- function(input, output) {
    
      # Render slider input depending on data frequency
    
      observe({
        # Create an xts object
        df_xts <- xts(df, order.by = as.Date(df$Date))
    
        # All_Dates = unique(df$Start_Date)
    
        Filtered_Dates <- df_xts[xts::endpoints(
          df_xts,
          on = input$Frequency
        )] %>% xts_to_tibble()
    
        output$Time_Series_UI <- renderUI({
          sliderInput("Date", "Date:",
            min = pull(slice_min(Filtered_Dates, date), date),
            max = pull(slice_max(Filtered_Dates, date), date),
            value = pull(slice_min(Filtered_Dates, date), date),
            step = 1,
            timeFormat = "%YYYY-%MM-%DD",
            animate = T
          )
        })
      })
    
      # Filter data for the date selected
      Filtered_Data <- reactive({
        req(input$Date)
        filter(df, Date == input$Date)
      })
    
    
      # Create the leaflet map
      output$Time_Series_Map <- renderLeaflet({
        leaflet(df) %>%
          addTiles() %>%
          setView(lat = 0, lng = 0, zoom = 2)
      })
    
      # Create data markers for selected date
      observe({
        # print(input$Date)
    
        leafletProxy("Time_Series_Map", data = Filtered_Data()) %>%
          addCircleMarkers(
            lng = ~lon, lat = ~lat,
            popup = ~id
          )
      })
    }
    
    # Run the application
    shinyApp(ui = ui, server = server)