Reputation: 3042
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
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