0

I want to create a shiny app that takes the first date range as inputs for the SQL command to query from the RSQLite db I created. However, when I run this without having a df object prior to running the app, it does not work. If I try to update the long lat slider ranges that are currently commented out, this crashes the app. I also keep getting this error: Warning in if (!loaded) { : the condition has length > 1 and only the first element will be used c("Loading required package: [", "Loading required package: input$timestamp", "Loading required package: 1") Failed with error: ‘'package' must be of length 1’

Can anyone help? I just want the user to give me the first date and last date ranges to query the database and then have dplyr do the rest of the filtering.

library(dplyr)
library(htmltools)
library(leaflet)
library(leafem)
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinythemes)
library(shinyBS)

#Create a formatted timestamp for filename
humanTime <- function() format(Sys.time(), "%Y-%m-%d_%H-%M-%OS")

#Create a Dummy Dataset
    get_data <- function(size){
  df <- data.frame(OBJECT_ID = seq(from =1, to = size, by = 1))
  df$LONGITUDE <- sample(seq(from=-20, to =160, by = 0.01), size, rep= TRUE)
  df$LATITUDE <- sample(seq(from = -10, to= 83, by = 0.01), size, rep= TRUE)
  df$LOCATION <- sample(c("A", "B", "C"), size, replace = T, prob = c(0.4, 0.4, 0.2))
  df$EQUIPMENT <- sample(c("E1", "E2", "E3", "E4"), size, replace = TRUE)
  startTime <- as.POSIXct("2016-01-01")
  endTime <- as.POSIXct("2019-01-31")
  df$DATE <- as.character(as.Date(sample(seq(startTime, endTime, 1), size))) #use as.Date to remove times
  df$WEEKDAY <- weekdays(as.Date(df$DATE))
  
  return(df)
}

#Is this necessary to get the ranges for the slider values?
df <- get_data(200)
df$DATE <- as.Date(df$DATE)
df <- df %>% mutate_if(is.character, as.factor)


ui <- navbarPage(
  id = "navBar",
  title = "Data Exploration",
  theme = shinytheme("cerulean"),
  shinyjs::useShinyjs(),
  selected = "Data",
  
  tabPanel("Data",
           fluidPage(
             sidebarPanel(
               div(id = "form",
                   dateRangeInput('timestamp', label = 'Date range input:', start = '', end = ''),
                   pickerInput('days_of_week', 'Choose Weekdays:', choices = c("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"), options = list(`actions-box` = TRUE), multiple = T),
                   sliderInput('long', "Longitude Range:", min = min(df$LONGITUDE),max = max(df$LONGITUDE), value = c(min(df$LONGITUDE), max(df$LONGITUDE)), step = 0.1),
                   sliderInput('lat', "Latitude Range:",  min = min(df$LATITUDE),max = max(df$LATITUDE), value = c(min(df$LATITUDE), max(df$LATITUDE)), step = 0.1),
                   pickerInput('location', "Select Location:", choices = unique(df$LOCATION), options = list(`actions-box` = TRUE), multiple = T),
                   pickerInput('equipment_type', "Choose Equipment:", choices = unique(df$EQUIPMENT), options = list(`actions-box` = TRUE), multiple = T),
                   actionButton("resetAll", "Reset Filters"),
                   selectInput("download_type", "Choose download formatt:", choices = c("CSV" = ".csv", "KML" = ".KML")))
             ),
             mainPanel(
               leafletOutput("datamap", width = "100%", height = 400),
               DT::DTOutput('datatable')))
  )
  
)#end the ui


server <- function(session, input, output){
  
  filter_by_dates <- reactive({
    require(input$timestamp[1])
    require(input$timestamp[2])
    my_conn <- dbConnect(RSQLite::SQLite(), "sample.db")
    df <- DBI::dbGetQuery(my_conn, paste0("SELECT * FROM Table_1 WHERE DATE >= '", input$timestamp[1], "' AND DATE <= '", input$timestamp[2], "'"))
    df$DATE <- as.Date(df$DATE)
    df <- df %>% mutate_if(is.character, as.factor)
    DBI::dbDisconnect(my_conn)
    return(df)
  })
  
  filter_by_all <- reactive({
    fd <- filter_by_dates()
    
    if (!is.null(input$days_of_week)) {
      fd <- filter(fd, WEEKDAY %in% input$days_of_week)
    }
    
    if (!is.null(input$long[1] & input$long[2])){
      fd <- filter(fd, LONGITUDE >= input$long[1] & LONGITUDE <= input$long[2])
    }
    
    if (!is.null(input$lat[1] & input$lat[2])){
      fd <- filter(fd, LATITUDE >= input$lat[1] & LATITUDE <= input$lat[2])
    }
    
    if (!is.null(input$location)) {
      fd <- filter(fd, LOCATION %in% input$location)
    }
    
    if (!is.null(input$equipment_type)) {
      fd <- filter(fd, EQUIPMENT %in% input$equipment_type)
    }
    
    return(fd)
  })
  
  observe({
    require(input$timestamp[1])
    require(input$timestamp[2])
    updatePickerInput(session, 'days_of_week', 'Choose Weekdays:', choices = sort(unique(filter_by_all()$WEEKDAY), decreasing = T), selected = sort(input$days_of_week, decreasing = T))
    #updateSliderInput(session, 'long', "Longitude Range:", min=min(filter_by_all()$LONGITUDE), max = max(filter_by_all()$LONGITUDE), value = c(input$long[1], input$long[2]))
    #updateSliderInput(session, 'lat', "Latitude Range:", min=min(filter_by_all()$LATITUDE), max = max(filter_by_all()$LATITUDE), value = c(input$lat[1], input$lat[2]))
    updatePickerInput(session, 'location', "Select Location:", choices = unique(filter_by_all()$LOCATION), selected = input$location)
    updatePickerInput(session, 'equipment_type', "Choose Equipment:", choices = unique(filter_by_all()$EQUIPMENT), selected = input$equipment_type)
  })
  
  #Map is updated by User inputs
  output$datamap <- renderLeaflet({
    leaflet(data = filter_by_all() ) %>%
      addCircleMarkers(
        lng = ~LONGITUDE,
        lat = ~LATITUDE,
        radius = 3) %>%
      addTiles(group = "ESRI") %>%
      addTiles(group = "OSM") %>%
      addProviderTiles("Esri.WorldImagery", group = "ESRI") %>%
      addProviderTiles("Stamen.Toner", group = "Stamen") %>%
      addLayersControl(baseGroup = c("ESRI", "OSM", "Stamen"))
  })
  

  output$datatable <- DT::renderDT({
    filter_by_all()
  }, server = FALSE) #this was used with SharedData doesn't work with downloading data so scrap

  #Allow the user to reset all their inputs
  observeEvent(input$resetAll, {
    reset("form")
  })
  
    
}#end server

shinyApp(ui, server)
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
casanoan
  • 27
  • 1
  • 5
  • Can you please reduce the question to a minimal reproducible example? https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/16532098 is a good start, https://reprex.tidyverse.org/index.html helps format such an example. – krlmlr Mar 03 '21 at 06:14
  • I tried to simplify it a little more just now. The main components that I need to show is the reactivity between setting the date range from user input and seeing how it affects the remaining filters. Right now it seems the only issue is the LONGITUDE and LATITUDE slider range values. They want some values but there's no dataframe until the user selects the date range – casanoan Mar 03 '21 at 11:25
  • Is Shiny necessary to demonstrate the problem? Can you create an example that avoids Shiny? – krlmlr Mar 04 '21 at 12:18
  • shiny here is necessary. I'm working on an application that gets the date range from the user and then it calls the database using that date range to store a dataframe object that can be filtered after. I have it working right now but I have to already have a dataframe oject stored. I'm working to eventually have the user give the daterange inputs that can be sent to a rest api to query directly. – casanoan Mar 04 '21 at 13:56

0 Answers0