0
votes

I'm trying to be an R Shiny app that utilizes a pre-built xgboost model and generates a prediction on user inputs to the model. IDEALLY, it would be reactive to their inputs so that users could see how the prediction changes based on making changes to their inputs (i.e. modifiable events).

My process so far has been to build the UI and then use the UI inputs to display a reactive data table as proof of concept that my data is getting into the model correctly (i.e. encoded the same way I trained the model).

Where I'm having problems is trying to take that reactive df and pass it to a function to generate a sparse matrix (or do anything to it for that matter). I feel like there's something fundamentally I'm missing in how to 'handle' the reactive df.

library("shiny") 
library(xgboost)

xgb.bst <- readRDS('xgb_bst.RDS')

ui <- shinyUI(
  pageWithSidebar(
    headerPanel("Calculator")
    ,
    sidebarPanel(
      selectInput("age", "Patient Age", 
                  choices = c("< 40" = 0,
                              "40 - 49" = 1,
                              "50 - 59" = 2,
                              "60 or older" = 3)),
      selectInput("bmi", "Patient BMI",
                  choices = c("< 30" = 0,
                              "30 - 39" = 1,
                              "40 - 49" = 2,
                              "50 - 59" = 3,
                              "60 or greater" = 4)),
      selectInput("race", "What is the patient's race?", 
                  choices = c("White" = 0,
                              "African American" = 1,
                              "Asian" = 4,
                              "Pacific Islander" = 1,
                              "Native American" = 3,
                              "Other/Not Reported" = 5)),

      checkboxInput("cardiach", 
                    label = "History of MI"),

      actionButton("submit","Submit")),

    mainPanel(uiOutput('table'))
  ))

server <- shinyServer(
  function(input,output,session){

    Data = reactive({
      if (input$submit > 0) {
        df <- data.frame(Age = input$age,
                         BMI = input$bmi,
                         Race = input$race,
                         Cardiac = as.integer(input$cardiac),
        return(list(df = df))
      }
    })

#    output$table <- renderTable({
#      if (is.null(Data())) {return()}
#      print(Data()$df)
#    }, 'include.rownames' = FALSE
#    , 'include.colnames' = TRUE
#    , 'sanitize.text.function' = function(x){x}
#    )

    df_matrix <- data.matrix(Data)
    mdata <- xgb.DMatrix(df_matrix)

    pred <- predict(xgb.bst, newdata = mdata)

  })

shinyApp(ui = ui, server = server)

And I keep getting errors such as:

Listening on http://127.0.0.1:3890
Warning: Error in : object of type 'closure' is not subsettable
  52: is.data.frame [#44]
  51: data.matrix
  50: server [#44]
Error : object of type 'closure' is not subsettable

I get the feeling I'm not handling the reactive data properly but I'm not entirely sure why or how. Any help would be appreciated. Even if it was just being able to print a summary of my reactive df. Commented code was how I displayed the reactive table.

1
Data is a reactive function. It should be called like Data() - cory
The problem with your code is that Data is a reactive function, but you are trying to define df_matrix and mdata as non-reactive objects. [Rstudio's documentation on reactivity][1] may be a helpful read. In your case, try chaining reactive's together by making df_matrix and mdata reactives that depend on Data [1]: shiny.rstudio.com/articles/reactivity-overview.html - ichbinallen

1 Answers

1
votes

Here's what you probably need. You can change the output type of 'table' as per your needs. -

# Use mainPanel(verbatimTextOutput('table')) in ui

server <- shinyServer(
  function(input,output,session){

    pred <- eventReactive(input$submit, {
      Data <- data.frame(Age = input$age,
                 BMI = input$bmi,
                 Race = input$race,
                 Cardiac = as.integer(input$cardiac), stringsAsFactors = F)
      df_matrix <- data.matrix(Data)
      mdata <- xgb.DMatrix(df_matrix)
      predict(xgb.bst, newdata = mdata)
    })

    output$table <- renderPrint({
      pred()
    })
  })

shinyApp(ui = ui, server = server)