J.Sabree
J.Sabree

Reputation: 2546

Why does my reactiveVal code fail in R Shiny when the same code works when part of a reactive?

When users select a date using the date range input, I want to convert the format of their selected date and then treat it like a character.

I can get my code to work when it's embedded in a larger reactive to filter my dataset, but I can't get it to work as it's own value. Because I need to use this character string across many areas of my app, I'd rather just write the code once as it's own reactiveVal than having to embed it within larger reactives.

Here's the code that fails (I only moved the from_date outside of the larger reactive):

library(shiny)
library(dplyr)
library(tidyr)
library(htmltools)
library(lubridate)
library(DT)
library(stringr)



ui = fluidPage(
    useShinyjs(),
    useShinydashboard(),
    tabsetPanel(
        tabPanel("Resource View", fluid = TRUE,
                 sidebarLayout(
                     sidebarPanel(
                         div(id = "inputs",
                             dateRangeInput(
                                 inputId = "date_filter",
                                 label = "Filter by Month and Year",
                                 start = today(),
                                 end = (today() + 90),
                                 min = "Apr-2021",
                                 max = NULL,
                                 format = "M-yyyy",
                                 startview = "month",
                                 weekstart = 0,
                                 language = "en",
                                 separator = " to ",
                                 width = NULL,
                                 autoclose = TRUE
                             ),
                             br()),
                     ),
                     mainPanel(
                         DT::DTOutput("resource_table"),

                     )
                 )
        )
        )
    )
server = function(input, output, session) {
    
    from_date <- reactiveVal({ tibble(date = as.character(input$date_filter[1]))
    
    
    from_date <- from_date %>%
        mutate(date = str_remove_all(date, "-..$")) %>%
        separate(date, into = c("year", "month"), sep = "-") %>%
        mutate(month = case_when(
            month == "01" ~ "jan",
            month == "02" ~ "feb",
            month == "03" ~ "mar",
            month == "04" ~ "apr",
            month == "05" ~ "may",
            month == "06" ~ "jun",
            month == "07" ~ "jul",
            month == "08" ~ "aug",
            month == "09" ~ "sep",
            month == "10" ~ "oct",
            month == "11" ~ "nov",
            month == "12" ~ "dec",
            TRUE~ "ERROR"
        )) %>%
        unite("month_year", c(month, year), sep = "_")
    
    from_date <- parse_character(from_date$month_year)
    })
    
    
    select_values <- reactive({
        data <- tibble(employee = c("Justin", "Corey","Sibley", "Justin", "Corey","Sibley", "Lisa", "NA"),
                       education = c("graudate", "student", "student", "graudate", "student", "student", "nurse", "doctor"),
                       fte_max_capacity = c(1, 2, 3, 1, 2, 3, 4, 5),
                       project = c("big", "medium", "small", "medium", "small", "small", "medium", "medium"),
                       aug_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       sep_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       oct_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       nov_2021 = c(1, 1, 1, 1, 1, 1, 2, 5))
        

        
        
        
        to_date <- tibble(date = as.character(input$date_filter[2]))
        
        to_date <- to_date %>%
            mutate(date = str_remove_all(date, "-..$")) %>%
            separate(date, into = c("year", "month"), sep = "-") %>%
            mutate(month = case_when(
                month == "01" ~ "jan",
                month == "02" ~ "feb",
                month == "03" ~ "mar",
                month == "04" ~ "apr",
                month == "05" ~ "may",
                month == "06" ~ "jun",
                month == "07" ~ "jul",
                month == "08" ~ "aug",
                month == "09" ~ "sep",
                month == "10" ~ "oct",
                month == "11" ~ "nov",
                month == "12" ~ "dec",
                TRUE~ "ERROR"
            )) %>%
            unite("month_year", c(month, year), sep = "_")  
        
        to_date <- parse_character(to_date$month_year)
        
        
        data %>%
            dplyr::select(employee, education, fte_max_capacity, project,
                          from_date():to_date)
        
    })
    
    output$resource_table <- renderDT({
        select_values()
    })
    
}
shinyApp(ui = ui, server = server)


And here's the code working perfectly when the from_date is embeded in the reactive for select_values().

library(shiny)
library(plotly)
library(shinyjs)
library(shinydashboard)
library(shinyWidgets) 
library(dplyr)
library(tidyr)
library(htmltools)
library(lubridate)
library(DT)
library(janitor)
library(readxl)
library(stringr)



ui = fluidPage(
    useShinyjs(),
    useShinydashboard(),
    tabsetPanel(
        tabPanel("Resource View", fluid = TRUE,
                 sidebarLayout(
                     sidebarPanel(
                         div(id = "inputs",
                             dateRangeInput(
                                 inputId = "date_filter",
                                 label = "Filter by Month and Year",
                                 start = today(),
                                 end = (today() + 90),
                                 min = "Apr-2021",
                                 max = NULL,
                                 format = "M-yyyy",
                                 startview = "month",
                                 weekstart = 0,
                                 language = "en",
                                 separator = " to ",
                                 width = NULL,
                                 autoclose = TRUE
                             ),
                             br()),
                     ),
                     mainPanel(
                         DT::DTOutput("resource_table"),

                     )
                 )
        )
        )
    )
server = function(input, output, session) {
    
    
    
    select_values <- reactive({
        data <- tibble(employee = c("Justin", "Corey","Sibley", "Justin", "Corey","Sibley", "Lisa", "NA"),
                       education = c("graudate", "student", "student", "graudate", "student", "student", "nurse", "doctor"),
                       fte_max_capacity = c(1, 2, 3, 1, 2, 3, 4, 5),
                       project = c("big", "medium", "small", "medium", "small", "small", "medium", "medium"),
                       aug_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       sep_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       oct_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       nov_2021 = c(1, 1, 1, 1, 1, 1, 2, 5))
        

        from_date <- tibble(date = as.character(input$date_filter[1]))
            
            
            from_date <- from_date %>%
                mutate(date = str_remove_all(date, "-..$")) %>%
                separate(date, into = c("year", "month"), sep = "-") %>%
                mutate(month = case_when(
                    month == "01" ~ "jan",
                    month == "02" ~ "feb",
                    month == "03" ~ "mar",
                    month == "04" ~ "apr",
                    month == "05" ~ "may",
                    month == "06" ~ "jun",
                    month == "07" ~ "jul",
                    month == "08" ~ "aug",
                    month == "09" ~ "sep",
                    month == "10" ~ "oct",
                    month == "11" ~ "nov",
                    month == "12" ~ "dec",
                    TRUE~ "ERROR"
                )) %>%
                unite("month_year", c(month, year), sep = "_")
            
            from_date <- parse_character(from_date$month_year)
        
        
        to_date <- tibble(date = as.character(input$date_filter[2]))
        
        to_date <- to_date %>%
            mutate(date = str_remove_all(date, "-..$")) %>%
            separate(date, into = c("year", "month"), sep = "-") %>%
            mutate(month = case_when(
                month == "01" ~ "jan",
                month == "02" ~ "feb",
                month == "03" ~ "mar",
                month == "04" ~ "apr",
                month == "05" ~ "may",
                month == "06" ~ "jun",
                month == "07" ~ "jul",
                month == "08" ~ "aug",
                month == "09" ~ "sep",
                month == "10" ~ "oct",
                month == "11" ~ "nov",
                month == "12" ~ "dec",
                TRUE~ "ERROR"
            )) %>%
            unite("month_year", c(month, year), sep = "_")  
        
        to_date <- parse_character(to_date$month_year)
        
        
        data %>%
            dplyr::select(employee, education, fte_max_capacity, project,
                          from_date:to_date)
        
    })
    
    output$resource_table <- renderDT({
        select_values()
    })
    
}
shinyApp(ui = ui, server = server)

In the answer, I'd really appreciate if you could also explain why your solution works and why my original attempt failed. Thank you!

Edit: Tried clarifying from_date by using variable names, but the app still crashes

    from_date <- reactiveVal({
        
        start_date <- tibble(date = as.character(input$date_filter[1]))
        
        
        date1 <- start_date %>%
            mutate(date = str_remove_all(date, "-..$")) %>%
            separate(date, into = c("year", "month"), sep = "-") %>%
            mutate(month = case_when(
                month == "01" ~ "jan",
                month == "02" ~ "feb",
                month == "03" ~ "mar",
                month == "04" ~ "apr",
                month == "05" ~ "may",
                month == "06" ~ "jun",
                month == "07" ~ "jul",
                month == "08" ~ "aug",
                month == "09" ~ "sep",
                month == "10" ~ "oct",
                month == "11" ~ "nov",
                month == "12" ~ "dec",
                TRUE~ "ERROR"
            )) %>%
            unite("month_year", c(month, year), sep = "_")
        
        date1 <- parse_character(date1$month_year)
    })
    

Upvotes: 0

Views: 491

Answers (2)

YBS
YBS

Reputation: 21349

You should be able to do from_date in one reactive.

  from_date <- reactive({
    fdate1 <- tibble(date = as.character(input$date_filter[1])) 
    fdate2 <- fdate1 %>%
      mutate(date = str_remove_all(date, "-..$")) %>%
      separate(date, into = c("year", "month"), sep = "-") %>%
      mutate(month = case_when(
        month == "01" ~ "jan",
        month == "02" ~ "feb",
        month == "03" ~ "mar",
        month == "04" ~ "apr",
        month == "05" ~ "may",
        month == "06" ~ "jun",
        month == "07" ~ "jul",
        month == "08" ~ "aug",
        month == "09" ~ "sep",
        month == "10" ~ "oct",
        month == "11" ~ "nov",
        month == "12" ~ "dec",
        TRUE~ "ERROR"
      )) %>%
      unite("month_year", c(month, year), sep = "_")
    fdate <- parse_character(fdate2$month_year)
    fdate
  })

Same goes for to_date.

Upvotes: 2

J.Sabree
J.Sabree

Reputation: 2546

Got it! So in line with the comment from @MrFlick, R was getting confused by trying to do so many things in one reactive. When I split each of those 3 segments into it's own reactive, I was able to make it work. If anyone knows a tighter way to get to the same end point, happy to look at other options:

library(shiny)
library(dplyr)
library(tidyr)
library(htmltools)
library(lubridate)
library(DT)
library(stringr)



ui = fluidPage(
    useShinyjs(),
    useShinydashboard(),
    tabsetPanel(
        tabPanel("Resource View", fluid = TRUE,
                 sidebarLayout(
                     sidebarPanel(
                         div(id = "inputs",
                             dateRangeInput(
                                 inputId = "date_filter",
                                 label = "Filter by Month and Year",
                                 start = today(),
                                 end = (today() + 90),
                                 min = "Apr-2021",
                                 max = NULL,
                                 format = "M-yyyy",
                                 startview = "month",
                                 weekstart = 0,
                                 language = "en",
                                 separator = " to ",
                                 width = NULL,
                                 autoclose = TRUE
                             ),
                             br()),
                     ),
                     mainPanel(
                         DT::DTOutput("resource_table"),
                         
                     )
                 )
        )
    )
)
server = function(input, output, session) {
    
    from_date_unclean <- reactive({
        
        tibble(date = as.character(input$date_filter[1])) 
        })
        
    from_date_midway <- reactive({
        from_date_unclean() %>%
            mutate(date = str_remove_all(date, "-..$")) %>%
            separate(date, into = c("year", "month"), sep = "-") %>%
            mutate(month = case_when(
                month == "01" ~ "jan",
                month == "02" ~ "feb",
                month == "03" ~ "mar",
                month == "04" ~ "apr",
                month == "05" ~ "may",
                month == "06" ~ "jun",
                month == "07" ~ "jul",
                month == "08" ~ "aug",
                month == "09" ~ "sep",
                month == "10" ~ "oct",
                month == "11" ~ "nov",
                month == "12" ~ "dec",
                TRUE~ "ERROR"
            )) %>%
            unite("month_year", c(month, year), sep = "_")
    })
        
    from_date <- reactive({
        parse_character(from_date_midway()$month_year)
    })
    
    
    to_date_unclean <- reactive({
        tibble(date = as.character(input$date_filter[2]))
    })
    
    to_date_midway <- reactive({
        to_date_unclean() %>%
        mutate(date = str_remove_all(date, "-..$")) %>%
        separate(date, into = c("year", "month"), sep = "-") %>%
        mutate(month = case_when(
            month == "01" ~ "jan",
            month == "02" ~ "feb",
            month == "03" ~ "mar",
            month == "04" ~ "apr",
            month == "05" ~ "may",
            month == "06" ~ "jun",
            month == "07" ~ "jul",
            month == "08" ~ "aug",
            month == "09" ~ "sep",
            month == "10" ~ "oct",
            month == "11" ~ "nov",
            month == "12" ~ "dec",
            TRUE~ "ERROR"
        )) %>%
        unite("month_year", c(month, year), sep = "_") 
    })
    
    to_date <- reactive({
        parse_character(to_date_midway()$month_year)
    })
        


    
    select_values <- reactive({
        data <- tibble(employee = c("Justin", "Corey","Sibley", "Justin", "Corey","Sibley", "Lisa", "NA"),
                       education = c("graudate", "student", "student", "graudate", "student", "student", "nurse", "doctor"),
                       fte_max_capacity = c(1, 2, 3, 1, 2, 3, 4, 5),
                       project = c("big", "medium", "small", "medium", "small", "small", "medium", "medium"),
                       aug_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       sep_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       oct_2021 = c(1, 1, 1, 1, 1, 1, 2, 5),
                       nov_2021 = c(1, 1, 1, 1, 1, 1, 2, 5))
        
        
        
        

        
        
        data %>%
            dplyr::select(employee, education, fte_max_capacity, project,
                          from_date():to_date())
        
    })
    
    output$resource_table <- renderDT({
        select_values()
    })
    
}
shinyApp(ui = ui, server = server)

Upvotes: 0

Related Questions