Search code examples
rdataframefor-loopshinyreactive-programming

for loop in reactive function: incompatible types (from closure to logical) in subassignment type fix


I am starting with shiny apps and would like to create a credit-calculator in a shiny app. However, it looks like I have a problem to implement a for-loop to create the output data.

UI

library(shiny)
shinyUI(
  fluidPage(
    titlePanel("User information"), # TITLE CONTENT
    sidebarLayout(
      sidebarPanel(("Enter your Information here"),
                   numericInput("credit.amount",
                             "How much is your credit?",
                             "")
                   ,sliderInput("yr.inter", 
                             "Interrest rate p.a.",
                             min = 0.5, 
                             max = 20, 
                             value = 8.5, 
                             step = 0.5
                             )
                   ,numericInput("mthl.rate",
                              "Your monthly payment",
                              "")
                   ), # SIDE BAR CONTENT
      mainPanel(("Credit decay"),
                textOutput("decaytime")
                ,tableOutput("creditmod")
                # ,textOutput("")
                ) # MAIN PANEL CONTENT
    )
  )
)

SERVER

library(shiny)
library(dplyr)
shinyServer(
  function(input, output){

    mthl.inter = reactive((input$yr.inter/1200)) # NUMERIC INPUT
    credit.amount = reactive(input$credit.amount) # SLIDER INPUT
    mthl.rate = reactive(input$mthl.rate) # NUMERIC INPUT

    # calculate repayment time

    credit.decay = reactive(
      as.numeric((log(1 - (mthl.inter() * credit.amount() / mthl.rate())) / 
        log(1 + mthl.inter())) * -1)
      ) 

    # calculate credit model 

    credit.model <- reactive({
      credit.df <- data.frame(rep(NA, credit.decay() %>% ceiling()))
      credit.df[1,1] <- credit.amount

      for (n in 2:(credit.decay() %>% ceiling()) ){
        credit.df[n,1] = credit.df[n-1,1] * (1 + mthl.inter()) - mthl.rate()
      }

      return(credit.df)

    })


    output$decaytime = renderText(credit.decay() %>% ceiling())
    output$creditmod = renderTable(credit.model())
  }
)

This returns the following error:

Warning: Error in <-: incompatible types (from closure to logical) in subassignment type fix

Your answers are very appreciated. Thank you very much, Max


Solution

  • Welcome to stackoverflow!

    You'll need req() to make sure no empty user inputs are passed to your function. Furthermore, I debounced your inputs to delay the calculation a little (so the user has some time to finish his inputs before the calculation starts)

    However it seems that you calculation only works for certain ratios of credit.amount and mthl.rate. You might need to add some further checks here.

    Please check the following:

    library(shiny)
    library(dplyr)
    
    ui <- fluidPage(
      titlePanel("Farm Statistic"), # TITLE CONTENT
      sidebarLayout(
        sidebarPanel(("Enter your Farm Information here"),
                     numericInput("credit_amount",
                                  "How much is your credit?",
                                  NA),
                     sliderInput("yr_inter", 
                                  "Interrest rate p.a.",
                                  min = 0.5, 
                                  max = 20, 
                                  value = 8.5, 
                                  step = 0.5
                     ),
                     numericInput("mthl_rate",
                                   "Your monthly payment",
                                   NA)
        ), # SIDE BAR CONTENT
        mainPanel(("Credit decay"),
                  textOutput("decaytime"),
                  tableOutput("creditmod")
                  # , textOutput("")
        ) # MAIN PANEL CONTENT
      )
    )
    
    server <- function(input, output, session) {
    
      mthl.inter.tmp <- reactive({req(input$yr_inter/1200)}) # NUMERIC INPUT
      credit.amount.tmp <- reactive({req(input$credit_amount)}) # SLIDER INPUT
      mthl.rate.tmp <- reactive({req(input$mthl_rate)}) # NUMERIC INPUT
    
      mthl.inter <- debounce(mthl.inter.tmp, 500)
      credit.amount <- debounce(credit.amount.tmp, 500)
      mthl.rate <- debounce(mthl.rate.tmp, 500)
    
      # calculate repayment time
      credit.decay = reactive({
        req(mthl.inter(), credit.amount(), mthl.rate())
        as.numeric((log(1 - (mthl.inter() * credit.amount() / mthl.rate())) / log(1 + mthl.inter())) * -1)
        }) 
    
      # calculate credit model 
      credit.model <- reactive({
        req(credit.decay())
        credit.df <- data.frame(rep(NA, credit.decay() %>% ceiling()))
        credit.df[1,1] <- credit.amount()
    
        for (n in 2:(credit.decay() %>% ceiling()) ){
          credit.df[n,1] = credit.df[n-1,1] * (1 + mthl.inter()) - mthl.rate()
        }
    
        return(credit.df)
    
      })
    
      output$decaytime = renderText(credit.decay() %>% ceiling())
      output$creditmod = renderTable(credit.model())
    }
    
    shinyApp(ui, server)