Your code is syntactically wrong and missing things for test, but here's a thought.
You are mistaking how reactivity works: you are making reactive something that does not need it, and missing those that do.
model_NaiveBayes
is unchanged by inputs, actions, or events, so it does not need to be reactive (you can make it so, but it's unnecessarily adding complexity to your app)
dfInput21
depends on user inputs, so needs to be reactive
predict_NaiveBayes
is dependent on the data from dfInput21
(which is reactive), so needs to be reactive
Another issue: assigning value to a variable within a block (e.g., reactive
, observe
, observeEvent
) does not make that variable available outside of that block. Think about it: you are saying that that variable (to which you just assigned) will change based on something else that happens. That is the definition of reactivity, so needs to be handled as such.
Also, I don't know how you are setting up the UI, but if predict_Models()
fires before input$F1
(...) is properly set, you'll see transient failures. For this, I recommend the use of req
to say effectively "I need dfInput21()
to be 'truthy' before you evaluate the rest of a block". ("Truthy" is based on things like not NULL
. See ?isTruthy
and the source shiny::isTruthy
for more.) There are many other things req
can be used for, not just variable "goodness", but also validation. For instance, req(input$F1 > 0)
works as one might expect. If the req
expression fails, the rest of the block is not executed (and the downstream UI elements are not adversely affected).
Finally, I find keeping data as its own reactive "thing" typically makes sense. If any other table/plot/block needs the data, then keeping the data by itself makes a lot of sense. Keeping it separate even if there's only one consumer adds very little complexity to the shiny internal-dependency table, but it is also quite expressive in that "this variable is always 'raw' data". (Related is that it might be useful to not immediately filter results from predict
, so I moved the [,1]
from the call to predict
to the presentation of it.
So a direct translation of your app could look like:
server <- function(input, output, session) {
model_NaiveBayes <- naiveBayes(outcome~., data=BC_bind21,probability=TRUE)#use naiveBayes
# submit action button
dfInput21 <- eventReactive(input$submit, {
req(input$F1,input$F2,input$F3)
data.frame(input$F1,input$F2,input$F3)
})
predict_Models <- reactive({
req(dfInput21())
predict(model_NaiveBayes, newdata = dfInput21(), type= "raw")
})
#show the result
output$result <- renderText({
req(predict_Models())
predict_Models()[,1]
})
}
If you wanted to reduce things a little, you could combine dfInput21
and predict_Models
, though you lose access to the "user-defined input data" as raw data (probably not a factor here).
server <- function(input, output, session) {
model_NaiveBayes <- naiveBayes(outcome~., data=BC_bind21,probability=TRUE)#use naiveBayes
# submit action button
predict_Models <- reactive({
req(input$F1,input$F2,input$F3)
dfInput21 <- data.frame(input$F1,input$F2,input$F3) # not available outside this block
predict(model_NaiveBayes, newdata = dfInput21, type= "raw")
})
#show the result
output$result <- renderText({
req(predict_Models())
predict_Models()[,1]
})
}