tonykuoyj
tonykuoyj

Reputation: 101

Plotting dynamic C5.0 decision tree in Shiny with reactiveValues()

I am developing a Shiny application to let users choose dependent / independent variables on demand then perform C5.0 to generate summary and a tree plot. However, there was error message when generating the plot regarding plot method could not find the appropriate object. This is an extended question of Plotting a dynamic C5.0 decision tree in Shiny. The plot method fails again after transforming iris to a reactiveValue() object rather than a simple dataframe, kindly find the code:

# ui.R
library(shiny)

fluidPage(
  titlePanel('Plotting Decision Tree'),
  sidebarLayout(
    sidebarPanel(
      h3('iris data'),
      uiOutput('choose_y'),
      uiOutput('choose_x'),
      actionButton('c50', label = 'Generate C5.0 summary and plot')
    ),
    mainPanel(
      verbatimTextOutput('tree_summary'),
      plotOutput('tree_plot_c50')
    )
  )
)

# server.R
library(shiny)
library(C50)

function(input, output) {
  output$choose_y <- renderUI({
    is_factor <- sapply(iris, FUN = is.factor)
    y_choices <- names(iris)[is_factor]
    selectInput('choose_y', label = 'Choose Target Variable', choices = y_choices)
  })

  output$choose_x <- renderUI({
    x_choices <- names(iris)[!names(iris) %in% input$choose_y]
    checkboxGroupInput('choose_x', label = 'Choose Predictors', choices = x_choices)
  })
  # tranforming iris to reactiveValues() object
  react_vals <- reactiveValues(data = NULL)
  react_vals$data <- iris

  observeEvent(input$c50, {
    form <- paste(isolate(input$choose_y), '~', paste(isolate(input$choose_x), collapse = '+'))
c50_fit <- eval(parse(text = sprintf("C5.0(%s, data = %s)", form, 'react_vals$data')))
    output$tree_summary <- renderPrint(summary(c50_fit))
    output$tree_plot_c50 <- renderPlot({
      plot(c50_fit)
    })
  })
}

Upvotes: 0

Views: 1171

Answers (1)

Weihuang Wong
Weihuang Wong

Reputation: 13118

My guess is that the plot method is looking for react_vals in the global environment; if that's the case, an easy solution (but not ideal) would be to assign iris to a variable in the global environment, using <<-. In your server.R:

# tranforming iris to reactiveValues() object
react_vals <<- reactiveValues(data = NULL)
react_vals$data <<- iris

A simple experiment confirms my guess; wrapping C5.0() and then plot() in a function throws an error:

library(C50)
test <- function(dat) {
  fit <- C5.0(Species ~ Sepal.Length, dat)
  plot(fit)
}

test(iris)
# Error in is.data.frame(data) : object 'dat' not found

Upvotes: 1

Related Questions