firmo23
firmo23

Reputation: 8404

Subset a dataframe using dateInput values as range in shiny

Hello I have a simple shiny app below. Here is the df:

location = c("100 ail","16th and Whitmore","40AB01 - ANTWERPEN","100 ail","16th and Whitmore","40AB01 - ANTWERPEN") 
date = c("2015-09-01 00:00:00","2016-03-06 19:00:00","2016-11-22 15:00:00","2018-02-01 09:30:00", "2018-02-01 03:00:00", "2017-03-07 10:00:00") 
pm25=c("FALSE","FALSE","FALSE","FALSE","FALSE","FALSE")
pm10=c("TRUE","FALSE","FALSE","TRUE","FALSE","FALSE")
no2=c("TRUE","FALSE","FALSE")
latitude=c(47.932907,41.322470,36.809700,47.932907,41.322470,36.809700)
longitude=c(106.92139000,-95.93799000
            ,-107.65170000,106.92139000,-95.93799000
            ,-107.65170000)

df = data.frame(location, date,latitude,longitude,pm25,pm10,no2)

and the app:

ui = fluidPage(

  uiOutput("dt"),
  uiOutput("dt2"),
  submitButton(text = "Submit", icon = NULL, width = NULL),
  shiny::dataTableOutput("merged") 
)

#server.r

#df$location <- gsub( " " , "+" , df$location)
server = function(input, output, session) {







  output$dt<-renderUI({

    dateInput('date',
              label = 'First Available Date',
              value = df$date
    )           


  })
  output$dt2<-renderUI({

    dateInput('date2',
              label = 'Last available Date',
              value = df$date
    )            


  })
  output$merged <- shiny::renderDataTable({
    df %>%
      filter(date >= input$dt & date <= input$dt2)
  })
}

shinyApp(ui = ui, server = server)

The df I want to display as datatable should take as inputs tha dates provided by the 2 selectInput() as range and changes its appearance everytime they are updated. Can this be done? Or dateInput() just displays the data that it takes from the beginning and cannot be used for subsetting?

Upvotes: 0

Views: 2608

Answers (1)

GyD
GyD

Reputation: 4072

First of all you need to convert your date column to date format. (I used lubridate for this purpose.

library(lubridate)

df = data.frame(location, date = as_datetime(date),latitude,longitude,pm25,pm10,no2)

The usage of renderUI is not needed in this case, since your data is not dynamic. (It works like this as well, just not ideal). I would just simply use dateInput:

dateInput('date',
            label = 'First Available Date',
            value = min(df$date)
)   ,
dateInput('date2',
          label = 'Last available Date',
          value = max(df$date)
)

Also, for dateInput setting value = df$date results in a warning, since the value argument takes a single value, but df$date is a vector of length 6. So instead I changed it to min(df$date) and max(df$date).

In your render function you need to specify the ids of the dateInputs, so use input$date and input$date2 instead of dt and dt2.

Note: when using dplyr filter: the operator & is not needed, you can just separate your filtering conditions with a comma.

df %>%
      filter(as_date(date) >= input$date, as_date(date) <= input$date2)

One more thing: I opted to convert date_time to date using as_date(date) for filtering. If you compare dates with date_time you might get unexpected results, like 2017-03-12 02:00 is greater than 2017-03-02.

Complete code:

library(dplyr)
library(shiny)
library(lubridate)

df = data.frame(location, date = as_datetime(date),latitude,longitude,pm25,pm10,no2)

ui = fluidPage(
  dateInput('date',
            label = 'First Available Date',
            value = min(df$date)
  )   ,
  dateInput('date2',
            label = 'Last available Date',
            value = max(df$date)
  ),
  submitButton(text = "Submit", icon = NULL, width = NULL),
  shiny::dataTableOutput("merged") 
)

server = function(input, output, session) {
  output$merged <- shiny::renderDataTable({
    df %>%
      filter(as_date(date) >= input$date, as_date(date) <= input$date2)
  })
}

shinyApp(ui = ui, server = server)

Upvotes: 3

Related Questions