Shiny Slider Input step by month

This is a solution that I use, but first I'd like to explain the logic:

  1. As mentioned above, timeFormat argument of the sliderInput() function does not give the required 1-month-step functionality. Instead, it simply formats underlying daily data, so stepping remains intact at a daily increment.
  2. sliderInput() has another argument step which can be used to explicitly define the stepping increment. However, it requires a single integer as an input, and therefore doesn't accept vectors/ranges. Given that months are of different lengths, a single integer is not right to use here. I tried to use lubridate::months(1) and lubridate::period(1, units = "months") -- to no avail unfortunately as both were automatically converted to an integer of 30 once rendered by the app, hence monthly increments were not retained.

I found a solution with shinyWidgets::sliderTextInput() which creates a character slider.

Assuming your dates are stored as yyyy-mm-dd dates in column Date of table d:

sliderTextInput(
  inputId    = "myID",
  label      = "myLabel",
  choices    = as.yearmon(unique(d$Date)),
  selected   = c(as.yearmon(min(d$Date)), as.yearmon(max(d$Date))),
  grid       = TRUE,
  width      = "100%"
)

With this you always step at monthly increments. as.yearmon() is used so your app shows slider labels in the MMM YYYY format.

Bear in mind that slider output is a character, so you need to back-transform into date:

  • as.Date(as.yearmon(input$myID[1])) for a start
  • as.Date(as.yearmon(input$myID[2])) for an end

There is a timeFormat function within the sliderInput. For more information visit Slider Input Widget.

EDIT:

To get the dates out and use them later on in your analysis, much credit goes to this question First day of the month from a POSIXct date time using lubridate and the function provided by Roland.

rm(list=ls())
library(shiny)
monthStart <- function(x) {
  x <- as.POSIXlt(x)
  x$mday <- 1
  as.Date(x)
}
ui <- basicPage(sliderInput("slider", "Time", min = as.Date("2010-01-01"),max =as.Date("2014-12-01"),value=as.Date("2014-12-01"),timeFormat="%b %Y"),
                textOutput("SliderText")
                )
server <- shinyServer(function(input, output, session){

  sliderMonth <- reactiveValues()
  observe({
    full.date <- as.POSIXct(input$slider, tz="GMT")
    sliderMonth$Month <- as.character(monthStart(full.date))
  })
  output$SliderText <- renderText({sliderMonth$Month})
})
shinyApp(ui = ui, server = server)

enter image description here