Ferroao
Ferroao

Reputation: 3042

how to predict based on linear models with reactive variables in shiny

I would like to kindly request some way to predict with lm (linear model) in R, that accepts reactive variables.
If you have a linear model "lm" with y and x, "predict" can be done for new data giving new values for x. I would like to do that for reactive y and x in a shiny app

In the following working example, I created somehow (arbitrarily, just to make it work) reactive y and x values for the lm, and also a input to give a changing new value (to be used as new x).

The objective is to correctly get the predicted y for the new (input) x considering y(), x() .

library(shiny)
library(EnvStats)
ui <- fluidPage ( 
  sidebarLayout(
  sidebarPanel (
  numericInput('variable1', 'new x', 0.1, min = 0, max = 100, step = 0.1)
  ),
  mainPanel (plotOutput('plot1') )
  )
  )
server <- function(input, output){
#  Initial data and linear regression that should be reactive,
# the dependency on input$variable1<1 is just an example to work with a lm based on reactive data. 
  y<- reactive (
    if (input$variable1<1)
    { y <- c(3.1, 3.25, 3.5, 4, 3.5, 5, 5.5) }
    else 
     { y <- c(.1, .25, .5, 1, 1.5, 2, 2.5) }
  )
  x<- reactive (
    if (input$variable1>=1)
    { x <- c(.1, .332, .631, .972, 1.201, 1.584, 1.912) }
    else 
    { x <- c(.1, .3,  .631, .972, 2.201, 2.584, 2.912) }
  )

output$plot1 <- renderPlot({
  # UNCORRECTED INITIAL VERSION some reactive functions are unnecessary 
  #  results <- reactive({ 
  #    r <- data.frame(y(),x())
  #  })
  #  lmod <- reactive ({ 
  #    mod1 <- lm(y()~ x(), data = results() 
  #    )
  #   x <-reactive ({ x <- input$variable1  })
  #  newdata <- reactive ({  data.frame(x() ) } )
  #  newdata.pred <- reactive ({  predict(lmod(),newdata(),level=1)
  #  })
  #  segments(input$variable1, 0, input$variable1, newdata.pred(), col = "red")
  # CORRECTED AFTER MRFLICK
    plot(x(),y())
    results <- data.frame(y=y(),x=x()) # reactive is not necessary because 
    lmod <- lm(y~x, data = results)    #of the reactive context (renderPlot)
    abline(lmod)  
    x <- input$variable1 
    newdata <- data.frame(x=x ) 
    newdata.pred2 <- predict(lmod,newdata,se.fit=TRUE)
    ci<- pointwise(newdata.pred2, coverage = 0.95, simultaneous = TRUE)

    newdata.pred <- predict(lmod,newdata)

        segments(input$variable1, 0, input$variable1, newdata.pred, col = "red")
        points(input$variable1, ci$lower, col = "magenta") 
        points(input$variable1, ci$upper, col = "magenta")
        text(input$variable1, newdata.pred, labels=paste("predicted",signif(newdata.pred, 3) ), pos =4, cex = 1.2)
        text(input$variable1, ci$upper, labels=paste("upper limit of pointwise confidence intervals",
                                                                     signif(ci$upper, 3) ), pos =4, cex = 1.2)
        text(input$variable1, ci$lower, labels=paste("lower limit of pointwise confidence intervals",
                                                        signif(ci$lower, 3) ), pos =4, cex = 1.2)
} )
} # end server
  shinyApp(ui, server)

Upvotes: 4

Views: 1966

Answers (1)

MrFlick
MrFlick

Reputation: 206401

It's better when using lm() and predict to have a properly named data.frame and use a proper formula. If you change these parts

results <- reactive({ 
  r <- data.frame(y=y(),x=x())
})

lmod <- reactive ({ 
  mod1 <- lm(y~x, data = results() )
 })

and

newdata <- reactive ({  data.frame(x=x() ) } )

I think you will get the behavior you want. Now both the model fitting data.frame and the predicting data.frame have a column named x and the formula used in the lm() clearly lists x as the variable used to predict y

Upvotes: 5

Related Questions