0
votes

I have a Shiny Dashboard app with three UIs. The first UI is a select input. The second UI is a dynamic select input that depends on the value of the first select input. The third UI is a dynamic slider input that depends on the value of the first two select inputs.

My issue is that all 3 UIs work to produce the resultant plot. However, before the generation of the plot, there is a brief moment in time where RStudio highlights to me the following warning:

Warning: Error in as.POSIXlt.default: do not know how to convert 'x' to class “POSIXlt”

I would like to be able to solve the above issue. I managed to isolate the problem to the renderUI and sliderInput subsection of my code:

min = min(year(first_filter()$Date)), max = max(year(first_filter()$Date)),

The year function from the lubridate package would return a numeric value which, in turn, would be fed into the between and filter function in my dplyr pipe. It should be the correct data type, but R indicates that the data type is wrong.

Thanks in advance!

My code is as follow:

A sample of the data:

df <- structure(list(Date = structure(c(1546214400, 1538265600, 1530316800, 
                                    1522454400, 1514678400, 1506729600, 1498780800, 1490918400, 1483142400, 
                                    1475193600, 1546214400, 1538265600, 1530316800, 1522454400, 1514678400, 
                                    1506729600, 1498780800, 1490918400, 1483142400, 1475193600, 1546214400, 
                                    1538265600, 1530316800, 1522454400, 1514678400, 1506729600, 1498780800, 
                                    1490918400, 1483142400, 1475193600, 1546214400, 1538265600, 1530316800, 
                                    1522454400, 1514678400, 1506729600, 1498780800, 1490918400, 1483142400, 
                                    1475193600, 1467244800, 1459382400, 1451520000, 1443571200, 1435622400, 
                                    1427760000, 1419984000, 1412035200, 1404086400, 1396224000, 1546214400, 
                                    1538265600, 1530316800, 1522454400, 1514678400, 1506729600, 1498780800, 
                                    1490918400, 1483142400, 1475193600, 1467244800, 1459382400, 1451520000, 
                                    1443571200, 1435622400, 1427760000, 1419984000, 1412035200, 1404086400, 
                                    1396224000), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
                 Group = c("Group B", "Group B", "Group B", "Group B", "Group B", 
                           "Group B", "Group B", "Group B", "Group B", "Group B", "Group B", 
                           "Group B", "Group B", "Group B", "Group B", "Group B", "Group B", 
                           "Group B", "Group B", "Group B", "Group B", "Group B", "Group B", 
                           "Group B", "Group B", "Group B", "Group B", "Group B", "Group B", 
                           "Group B", "Group A", "Group A", "Group A", "Group A", "Group A", 
                           "Group A", "Group A", "Group A", "Group A", "Group A", "Group A", 
                           "Group A", "Group A", "Group A", "Group A", "Group A", "Group A", 
                           "Group A", "Group A", "Group A", "Group A", "Group A", "Group A", 
                           "Group A", "Group A", "Group A", "Group A", "Group A", "Group A", 
                           "Group A", "Group A", "Group A", "Group A", "Group A", "Group A", 
                           "Group A", "Group A", "Group A", "Group A", "Group A"), Subgroup = c("Subgroup A", 
                                                                                                "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", 
                                                                                                "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup B", 
                                                                                                "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", 
                                                                                                "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup C", 
                                                                                                "Subgroup C", "Subgroup C", "Subgroup C", "Subgroup C", "Subgroup C", 
                                                                                                "Subgroup C", "Subgroup C", "Subgroup C", "Subgroup C", "Subgroup A", 
                                                                                                "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", 
                                                                                                "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", 
                                                                                                "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", 
                                                                                                "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup A", "Subgroup B", 
                                                                                                "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", 
                                                                                                "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", 
                                                                                                "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B", 
                                                                                                "Subgroup B", "Subgroup B", "Subgroup B", "Subgroup B"), 
                 Value = c(4.3, 4.4, 4.4, 4.5, 5.3, 5.4, 5.4, 5.4, 5.4, 5.44, 
                           31.5, 30.7, 29.5, 28.9, 29.2, 29.2, 29.2, 28.6, 27.6, 28.1, 
                           99.2, 99.2, 99.2, 100, 100, 100, 100, 98.3, 100, NA, 3.5, 
                           3.5, 3.5, 3.4, 3.5, 3.5, 3.4, 3.4, 3.6, 3.4, 3.53, 3.56, 
                           3.45, 3.16, 2.74, 2.88, 2.81, 2.57, 2.59, 2.47, 39.3, 41.4, 
                           40.3, 40.5, 37.3, 36.9, 36.4, 36.2, 39.8, 40.8, 40.2, 40.5, 
                           40.1, 33.9, 37.9, 38.6, 38.3, 39.8, 39.5, 40.8)), row.names = c(NA, 
                                                                                           -70L), class = c("tbl_df", "tbl", "data.frame"))


df$Date <- as.Date(df$Date, format = "%d/%m/%Y")

The UI:

# Define UI for application
ui <- dashboardPage(

  # Application title
  dashboardHeader(title = "App"),

  # Dashboard Sidebar
  dashboardSidebar(

    sidebarMenu(

      menuItem("Data", tabName = "data_tab")
    )
  ),

  dashboardBody(

    tabItems(

      tabItem(tabName = "data_tab",
              fluidRow(
                box(
                  selectInput("Group_selector",
                          "Select Group",
                          choices = unique(df$Group)),

                  # Add a UI Output to select Subgroup and Date range
                  uiOutput("dyn_metric"),
                  uiOutput("dyn_slider")
                ),

                box(
                  # Produce output using plotly
                  plotlyOutput("plot")
                )
              )
      )
    )
  )
)

The server:

library(shiny)
library(shinydashboard)
library(dplyr)
library(plotly)
library(lubridate)

# Define server logic required to plot trend
server <- function(input, output) {

  # Render a UI for selecting of Subgroup metric
  output$dyn_metric <- renderUI({
    selectInput("Subgroup_selector",
                "Select Subgroup", choices = unique(df[df$Group == input$Group_selector, "Subgroup"]))
  })

  # Render a UI for selecting date range
  output$dyn_slider <- renderUI({
    sliderInput("date_range_selector", "Select Date Range", 
                min = min(year(first_filter()$Date)),
                max = max(year(first_filter()$Date)),
                value = c(max(year(first_filter()$Date)-1),
                          max(year(first_filter()$Date))),
                sep = "")
  })

  # Filter by Group and Subgroup first
  first_filter <- reactive({
    if(is.null(input$Subgroup_selector)) {
      return(NULL)
    }

    df %>%
      filter(Group == input$Group_selector & Subgroup == input$Subgroup_selector)
  })

  # Filter by Date Range next
  second_filter <- reactive({
    if(is.null(input$date_range_selector)) {
      return(NULL)
    }

    first_filter() %>%
      filter(between(year(Date), input$date_range_selector[1], input$date_range_selector[2]))
  })

  # Render plot using second filtered dataset
  output$plot <- renderPlotly({
    if(is.null(second_filter())) {
      return()
    }

    plot_ly(second_filter(), x = ~Date, y = ~Value, type = "scatter", mode = "lines+markers")
  })
}

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

1 Answers

1
votes

Overview

The main issue here is that when the app is initialized first_filter()$Date is NULL, as you set it in first_filter <- reactive(...). This can be fixed by placing a req(first_filter()) in output$dyn_slider <- renderUI(...) as shown below.

req() is the preferred method to check if inputs and reactive variables are available. It tests for "truthy-ness". Even though the rest of the code works, as a best practice I would recommend you change it to use req() instead of,

   if(is.null(input$sample)) {
      return(NULL)
    }

Fixed Code

# Define UI for application
ui <- dashboardPage(

  # Application title
  dashboardHeader(title = "App"),

  # Dashboard Sidebar
  dashboardSidebar(

    sidebarMenu(

      menuItem("Data", tabName = "data_tab")
    )
  ),

  dashboardBody(

    tabItems(

      tabItem(tabName = "data_tab",
              fluidRow(
                box(
                  selectInput("Group_selector",
                              "Select Group",
                              choices = unique(df$Group)),

                  # Add a UI Output to select Subgroup and Date range
                  uiOutput("dyn_metric"),
                  uiOutput("dyn_slider")
                ),

                box(
                  # Produce output using plotly
                  plotlyOutput("plot")
                )
              )
      )
    )
  )
)

library(shiny)
library(shinydashboard)
library(dplyr)
library(plotly)
library(lubridate)

# Define server logic required to plot trend
server <- function(input, output) {

  # Render a UI for selecting of Subgroup metric
  output$dyn_metric <- renderUI({
    selectInput("Subgroup_selector",
                "Select Subgroup", choices = unique(df[df$Group == input$Group_selector, "Subgroup"]))
  })

  # Render a UI for selecting date range
  output$dyn_slider <- renderUI({
    req(first_filter())
    sliderInput("date_range_selector", "Select Date Range", 
                min = min(year(first_filter()$Date)),
                max = max(year(first_filter()$Date)),
                value = c(max(year(first_filter()$Date)-1),
                          max(year(first_filter()$Date))),
                sep = "")
  })

  # Filter by Group and Subgroup first
  first_filter <- reactive({
    if(is.null(input$Subgroup_selector)) {
      return(NULL)
    }

    df %>%
      filter(Group == input$Group_selector & Subgroup == input$Subgroup_selector)
  })

  # Filter by Date Range next
  second_filter <- reactive({
    if(is.null(input$date_range_selector)) {
      return(NULL)
    }

    first_filter() %>%
      filter(between(year(Date), input$date_range_selector[1], input$date_range_selector[2]))
  })

  # Render plot using second filtered dataset
  output$plot <- renderPlotly({
    if(is.null(second_filter())) {
      return()
    }

    plot_ly(second_filter(), x = ~Date, y = ~Value, type = "scatter", mode = "lines+markers")
  })
}

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