UI
rf_wf <- readRDS("rf_iris_workflow.rds")
# Fungsi median aman
med_val <- function(x) median(x, na.rm = TRUE)
ui <- fluidPage(
titlePanel("Iris Species Prediction (Random Forest)"),
tags$small("Model dilatih dari dataset iris bawaan R."),
br(),
tabsetPanel(
# TAB 1: APLIKASI
tabPanel("Aplikasi",
tabsetPanel(
# SINGLE PREDICTION
tabPanel("Single Prediction",
sidebarLayout(
sidebarPanel(
numericInput("sl", "Sepal Length", value = med_val(iris$Sepal.Length)),
numericInput("sw", "Sepal Width", value = med_val(iris$Sepal.Width)),
numericInput("pl", "Petal Length", value = med_val(iris$Petal.Length)),
numericInput("pw", "Petal Width", value = med_val(iris$Petal.Width)),
actionButton("predict_one", "Prediksi")
),
mainPanel(
h4("Hasil Prediksi"),
verbatimTextOutput("single_pred"),
DTOutput("single_proba")
)
)
),
# BATCH PREDICTION
tabPanel("Batch Prediction",
fileInput("csv_file", "Upload CSV tanpa kolom Species", accept = ".csv"),
DTOutput("batch_table"),
br(),
downloadButton("download_preds", "Download Hasil Prediksi")
)
)
),
# TAB 2: MODEL PERFORMANCE
tabPanel("Model Performance",
h4("Confusion Matrix"),
verbatimTextOutput("conf_mat_print"),
h4("Accuracy"),
verbatimTextOutput("acc_print")
)
)
)
Server
server <- function(input, output, session) {
# SINGLE PREDICTION
observeEvent(input$predict_one, {
newdat <- tibble(
Sepal.Length = input$sl,
Sepal.Width = input$sw,
Petal.Length = input$pl,
Petal.Width = input$pw
)
cls <- predict(rf_wf, new_data = newdat, type = "class")
prb <- predict(rf_wf, new_data = newdat, type = "prob")
output$single_pred <- renderText({
paste("Prediksi species:", cls$.pred_class)
})
output$single_proba <- renderDT({
datatable(prb, options = list(dom = "t"))
})
})
# BATCH PREDICTION
batch_data <- reactive({
req(input$csv_file)
df <- readr::read_csv(input$csv_file$datapath, show_col_types = FALSE)
validate(
need(all(c("Sepal.Length","Sepal.Width","Petal.Length","Petal.Width") %in% names(df)),
"Kolom harus lengkap: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width")
)
df
})
preds_df <- reactive({
df <- batch_data()
cls <- predict(rf_wf, new_data = df, type = "class")
prb <- predict(rf_wf, new_data = df, type = "prob")
bind_cols(df, tibble(Predicted = cls$.pred_class), prb)
})
output$batch_table <- renderDT({
datatable(preds_df(), options = list(pageLength = 10))
})
output$download_preds <- downloadHandler(
filename = function() "iris_predictions.csv",
content = function(file) {
readr::write_csv(preds_df(), file)
}
)
# Confusion Matrix + Accuracy
output$conf_mat_print <- renderPrint(conf_matrix)
output$acc_print <- renderPrint(acc)
}
shinyApp(ui, server)
Shiny applications not supported in static R Markdown documents