tonykuoyj tonykuoyj - 2 months ago 38
R Question

Plotting a dynamic C5.0 decision tree in Shiny

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. Does anyone know the solution? 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)
})

observeEvent(input$c50, {
c50_fit <- C5.0(as.formula(paste(isolate(input$choose_y), '~', paste(isolate(input$choose_x), collapse = '+'))), data = iris)
output$tree_summary <- renderPrint(summary(c50_fit))
output$tree_plot_c50 <- renderPlot({
plot(c50_fit)
})
})
}

Answer

In your server.R try

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)
  })

  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 = iris)", form)))
    output$tree_summary <- renderPrint(summary(c50_fit))
    output$tree_plot_c50 <- renderPlot({
      plot(c50_fit)
    })
  })
}

Explanation. The plot method appears to be looking for the terms specified in the call element of the returned value from C5.0(), and throws an error when they are not found. In your case, this refers to the input object. The workaround is to call C5.0() with the formula fully specified (e.g. Species ~ Sepal.Length + Petal.Width) through the eval(parse(text = ...)) construction.

Comments