1
votes

In this part of my Shiny app, I'll do a 'linear model' (lm()) regression, using the variables the user selects. There are three inputs:

  1. input$lmTrendFun is a selectInput(), with the options c("Linear", "Exponential", "Logarithmic", "Quadratic", "Cubic"):

    selectInput("lmTrendFun", "Select the model for your trend line.", 
                choices = c("Linear", "Exponential", "Logarithmic", "Quadratic", "Cubic"))
    
  2. The second input is input$lmDep, and it's a selectInput() too. I created a updateSelectInput first inside an observe() reactive function, so the choices are the column names from the imported tibble.

  3. The third input is input$lmInd and it's a checkboxGroupInput(), the choices being all the column names other than the one that's already the input$lmInd.

From that I want this output: the lm() (or rather, summary.lm() or summary(lm())) result for those variables. If I knew which they were, it would be simple:

if(input$lmTrendFun == "Linear"){
    form <- yname ~ x1 + x2
}else if(input$lmTrendFun == "Exponential"){
    form <- yname~ exp(x1) + exp(x2)
}else if(input$lmTrendFun == "Logarithmic"){
    form <- yname~ log(x1) + log(x2)
}else if(input$lmTrendFun == "Quadratic"){
    form <- yname ~ poly(x1, 2) + poly(x2, 2)
}else if(input$lmTrendFun == "Cubic"){
    form <- y ~ poly(x1, 3) + poly(x2, 3)
}

[...]
lm(form, data = .)

where the data (.) has the columns yname, x1 and x2.

However, I don't. So I believe I need some more generic function that can create the formula. How can this be done?

2

2 Answers

2
votes
formulizer <- function() as.formula(paste0( input$lmDep, "~", switch(input$lmTrendFun, 
            Linear = paste0(input$lmInd, collapse=" + "),
            Logarithmic =  paste0("exp(", input$lmInd,")", collapse=" + "),
            Quadratic =  paste0("poly(", input$lmInd,", 2)", collapse=" + "),
            Cubic =  paste0("poly(", input$lmInd,", 3)", collapse=" + ") )))
> input <- list(lmInd=paste0("V", 1:5), lmTrendFun="Linear", lmDep="Vp")
> formulaizer()
Vp ~ V1 + V2 + V3 + V4 + V5
<environment: 0x7fad1cf63d48>
> input <- list(lmInd=paste0("V", 1:5), lmTrendFun="Logarithmic", lmDep="Vp")
> formulizer()
Vp ~ exp(V1) + exp(V2) + exp(V3) + exp(V4) + exp(V5)
<environment: 0x7fad01e694d0>
> input <- list(lmInd=paste0("V", 1:5), lmTrendFun="Quadratic", lmDep="Vp")
> formulizer()
Vp ~ poly(V1, 2) + poly(V2, 2) + poly(V3, 2) + poly(V4, 2) + 
    poly(V5, 2)
<environment: 0x7fad01f51d20>
> input <- list(lmInd=paste0("V", 1:5), lmTrendFun="Cubic", lmDep="Vp")
> formulizer()
Vp ~ poly(V1, 3) + poly(V2, 3) + poly(V3, 3) + poly(V4, 3) + 
    poly(V5, 3)
<environment: 0x7fad01f59690>
0
votes

Consider switch with vectorized paste0 to build terms with transformations and then pass terms into reformulate. Adjust below inputs to actual Shiny variables:

dep_term <- ...
ind_terms <- ...

form <- switch(input$lmTrendFun,
                Linear = reformulate(ind_terms, response="yname"),
                Exponential = reformulate(paste0("exp(", ind_terms, ")"), response=dep_term),
                Logarithmic = reformulate(paste0("log(", ind_terms, ")"), response=dep_term),
                Quadratic = reformulate(paste0("poly(", ind_terms, ", 2)"), response=dep_term),
                Cubic = reformulate(paste0("poly(", ind_terms, ", 3)"), response=dep_term)
        )

Online Demo