2

Aim

I want to use a for loop in a shiny app. The code below will work without the for loop, but then fails to work with it.

Attempt

library(shiny) library(dplyr) library(lubridate) #create table dates <- seq(as.Date("2020-01-01"), as.Date("2022-04-01"), by="months") supply <- floor(runif(28, min = 80000, max = 100000)) demand <- rep(0, length(dates)) shortfall <- ifelse(demand - supply > 0, demand -supply, 0) df <- bind_cols(dates, supply, demand, shortfall) names(df) <- c("dates", "supply", "demand", "shortfall") # Define UI ---- ui <- navbarPage( titlePanel("Supply & Demand"), tabPanel(title = "Demand", mainPanel(h3("Demand", align = "center"), plotOutput(outputId = "demand")), sidebarPanel(sliderInput(inputId = "A", label = "A", min = 0, max = 50000, value = 5000), sliderInput(inputId = "B", label = "B", min = 0, max = 50000, value = 5000), sliderInput(inputId = "C", label = "C", min = 0, max = 50000, value = 5000))), tabPanel(title = "Table", mainPanel(h3("Table", align = "center"), tableOutput(outputId = "table"))) ) # Define server logic ---- server <- function(input, output) { df_ <- reactive({ df %>% mutate(demand = input$A + input$B + input$C, shortfall = rep(0, 28), returning_shortfall = c(10000, rep(0, 27)), stored_shortfall = rep(0, 28), total_demand = rep(0, 28)) }) df2_ <- reactive({ for (i in 2:length(df_()$dates)) { df_()$total_demand[i] = df_()$demand[i] + df_()$returning_shortfall[i-1] df_()$shortfall[i] = ifelse(df_()$total_demand[i] - df_()$supply[i] > 0, df_()$total_demand[i] - df_()$supply[i], 0) df_()$returning_shortfall[i] = df_()$shortfall[i-1] * 0.15 df_()$stored_shortfall[i] = df_()$stored_shortfall[i-1] + df_()$shortfall[i] * 0.15 } }) #Table output$table <- renderTable(df2_()) } # Run the app ---- shinyApp(ui = ui, server = server) 

Error message

Warning: Error in =: invalid (NULL) left side of assignment 113: <reactive:df2_> [C:/Users/user/filename] 97: df2_ 96: renderTable 95: func 82: renderFunc 81: output$table 1: runApp 

Outcome Sought

Tha main challenge is creating a column that where each value relies on a previous row's value. "For loops" seems to solve that problem, but it does not work in shiny.

3
  • 1
    You cannot access reactive components (e.g., df_) outside of a reactive block (such as *reactive, observe*, render*, etc). Add your logic either within the df_ initial-definition reactive, or create a second reactive block that uses df_() and creates a new frame (e.g., df2_ <- reactive(...)). Commented Apr 1, 2021 at 12:30
  • Thanks r2evans, I've put the for loop in a second reactive and now the app loads. However, I'm now getting the error message: "invalid (NULL) left side of assignment" instead of the table showing up. Any ideas? Commented Apr 1, 2021 at 12:48
  • You shiny app here isn't updated, so it could be a number of things. Please update your question with current code. Thanks! Commented Apr 1, 2021 at 12:49

1 Answer 1

3

You just need one reactive object. Try this

library(shiny) library(dplyr) library(lubridate) #create table dates <- seq(as.Date("2020-01-01"), as.Date("2022-04-01"), by="months") supply <- floor(runif(28, min = 8000, max = 20000)) demand <- rep(0, length(dates)) shortfall <- ifelse(demand - supply > 0, demand -supply, 0) df1 <- bind_cols(dates, supply, demand, shortfall) names(df1) <- c("dates", "supply", "demand", "shortfall") # Define UI ---- ui <- navbarPage( titlePanel("Supply & Demand"), tabPanel(title = "Demand", mainPanel(h3("Demand", align = "center"), plotOutput(outputId = "demand")), sidebarPanel(sliderInput(inputId = "A", label = "A", min = 0, max = 50000, value = 5000), sliderInput(inputId = "B", label = "B", min = 0, max = 50000, value = 5000), sliderInput(inputId = "C", label = "C", min = 0, max = 50000, value = 5000))), tabPanel(title = "Table", mainPanel(h3("Table", align = "center"), tableOutput(outputId = "table"))) ) # Define server logic ---- server <- function(input, output) { df2 <- reactive({ df <- df1 %>% mutate(demand = input$A + input$B + input$C, shortfall = rep(0, 28), returning_shortfall = c(10000, rep(0, 27)), stored_shortfall = rep(0, 28), total_demand = rep(0, 28)) for (i in 2:length(df$dates)) { df$total_demand[i] <- df$demand[i] + df$returning_shortfall[i-1] df$shortfall[i] <- ifelse(df$total_demand[i] - df$supply[i] > 0, df$total_demand[i] - df$supply[i], 0) df$returning_shortfall[i] <- df$shortfall[i-1] * 0.15 df$stored_shortfall[i] <- df$stored_shortfall[i-1] + df$shortfall[i] * 0.15 } df }) #Table output$table <- renderTable(df2()) } # Run the app ---- shinyApp(ui = ui, server = server) 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.