2

I am just starting out with Shiny and using it to show wind frequency outputs (speed and direction) for a selected site.

The Issue

Each data set has a different date range and I cant seem to return these variable date ranges back to the dateRangeInput in the UI when the user selects a different site.

If a date is selected that is outside of the selected data set range, Shiny errors and displays red text everywhere. To solve this I am using the min/max ranges to feed into the dataRangeInput.

My Code Sample So Far

The user selects a site from a drop down menu in the UI 'selectInput' which creates the variable input/ID "df".

The only way I can get anything to work is by passing the date range as a global variable using the date range of a particular data set however this is effectively a manual process:

Create some sample data (In the actual data the dates are date/time formatted):

library(shiny)
library(openair)
library(ggplot2)

date<- c("2017-01-01","2017-01-02","2017-01-03","2017-01-04")
ws<-c(rep(0:3,1))
SiteA <- data.frame(date,ws,stringsAsFactors = FALSE)

date<- c("2017-01-01","2017-01-02","2017-01-03","2017-01-04","2017-01-05", "2017-01-06")
ws<-c(rep(0:5,1))
SiteB <- data.frame(date,ws,stringsAsFactors = FALSE)

Extract min and max from the data (this is where I need assistance):

# Date ranges currently fixed to SiteA (need this to be dynamic based on selection)   
mystartdate <- as.character(format(as.Date(min(SiteA$date))),"yyyy-mm-dd")
myenddate <- as.character(format(as.Date(max(SiteA$date))),"yyyy-mm-dd")

These dates are then passed to the date range in the UI:

ui <- fluidPage(
    titlePanel("title"),

    sidebarLayout(
            sidebarPanel(
                    selectInput("df","Choose a Site:",
                                choices = c(
                                        "Site A" = 'SiteA',
                                        "Site B" = 'SiteB')
                    ),           

                    dateRangeInput("date", "Select the date range:",
                                   start = mystartdate, # Start date of the selected df
                                   end = myenddate, # End date of the selected df
                                   min = mystartdate,
                                   max = myenddate,
                                   format = "yyyy-mm-dd")
            ),
            mainPanel(
                    strong(paste("Frequency Distribution:")),
                    plotOutput("hist")
            )       
    )
)

The date ranges are then passed as inputs to filter the plots input$date[1] and input$date[2].

server <- function(input, output) {

    df <- reactive({
            x <- get(input$df)
    })

    output$hist <- renderPlot({
            df <- df() # df is the user selected dataset
            dfhist<- selectByDate(df, start = input$date[1], end = input$date[2])
            ggplot(df, aes(df$ws)) +
                    geom_histogram(fill = "blue", bins = 50) +
                    labs(x="Wind Speed (m/s)", y="Count")

    })
}               

shinyApp(ui = ui, server = server)

My Question:

How do I extract the min/max dates from the selected data sets (SiteA or SiteB) and return these to the dateRangeInput cells?

Any ideas/pointers would be much appreciated. Thanks

Nick
  • 276
  • 2
  • 13
  • it is complicated to execute your code because it is not a reproducible example. How is the object `SiteA$date` ? – Winicius Sabino Feb 06 '18 at 02:18
  • Please check this link, for help you I need at least one example of your `SiteA` object [how to make a reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) – Winicius Sabino Feb 06 '18 at 02:25
  • Thanks, I've added some sample data. Apologies for the confusion. Didn't want to make the code too long. But hopefully this helps. – Nick Feb 06 '18 at 03:26
  • OK. I'll post the answer – Winicius Sabino Feb 06 '18 at 03:44

1 Answers1

4

I extract the min / max data from the selected data sets (SiteA or SiteB) and return these to the dateRangeInput cells. And I made the subset in the dataframe according to the date chosen on the dataRangeInput to display the plot.I believe this satisfies all your app.

library(shiny)
library(openair)
library(ggplot2)
library(readr)


ui <- fluidPage(
  titlePanel("title"),

  sidebarLayout(
    sidebarPanel(
      selectInput("df","Choose a Site:",
                  choices = c(
                    "Site A" = 'SiteA',
                    "Site B" = 'SiteB')
      ),
       uiOutput("dateRange")


    ),
    mainPanel(
      strong(paste("Frequency Distribution:")),
      plotOutput("hist")
    )       
  )
)

server <- function(input, output, session) {
  df <- reactive({
    if(input$df == "SiteA"){
      date<- c("2017-01-01","2017-01-02","2017-01-03","2017-01-04")
      ws<-c(rep(0:3,1))
      SiteA <- data.frame(date,ws,stringsAsFactors = FALSE)
      x <- SiteA
    }
    if(input$df == "SiteB"){
      date<- c("2017-01-01","2017-01-02","2017-01-03",
                "2017-01-04","2017-01-05", "2017-01-06")
      ws<-c(rep(0:5,1))
      SiteB <- data.frame(date,ws,stringsAsFactors = FALSE)
      x <- SiteB
   }
      return(x)
  })



  output$dateRange <- renderUI({
    dateRangeInput("date", "Select the date range:",
                   start = 
    as.character(format(as.Date(min(df()$date))),"yyyy-mm-dd"), # Start 
                        end = 
    as.character(format(as.Date(max(df()$date))),"yyyy-mm-dd"), # End 
               min = 
    as.character(format(as.Date(min(df()$date))),"yyyy-mm-dd"),
               max = 
    as.character(format(as.Date(max(df()$date))),"yyyy-mm-dd"),
               format = "yyyy-mm-dd")

  })



  output$hist <- renderPlot({
    df <- df() # df is the user selected dataset
    dfhist<- subset(df, date >= as.Date(input$date[1]) & date <= 
                     as.Date(input$date[2]) )
    ggplot(dfhist, aes(dfhist$ws)) +
      geom_histogram(fill = "blue", bins = 50) +
      labs(x="Wind Speed (m/s)", y="Count")

  })


}

shinyApp(ui=ui, server = server)
Winicius Sabino
  • 1,486
  • 8
  • 17