Build Interactive Machine Learning Web Apps with R Shiny
As a data scientist, one of the best ways to share your work and enable others to interact with your machine learning models is to build web applications. While there are many ways to create data science web apps, the R Shiny package makes it easy to build powerful interactive apps entirely in R – no web development skills required!
In this step-by-step guide, you‘ll learn how to use R Shiny to create an app that lets users interactively build and evaluate machine learning models. By the end, you‘ll be able to load a dataset, let users select variables, choose an algorithm, tune parameters, and see the results – all through an intuitive point-and-click interface.
So let‘s dive in and see how R Shiny can help bring your models to life!
What is R Shiny?
Shiny is an open source R package developed by RStudio that enables you to turn your analyses into interactive web applications. It combines the computational power of R with the interactivity of modern web browsers, making it easy for users to generate output by manipulating input controls like sliders, drop-downs and text fields.
Shiny apps have two components:
- A user interface (ui) script that controls the layout and appearance
- A server script that contains the app logic
When a user visits your app URL, ui.R defines the controls available and server.R uses reactive programming to update outputs in response to user inputs. The two scripts work in harmony to create a seamless interactive experience.
Getting Started
First, make sure you have the latest version of R and RStudio installed. Open RStudio and install the Shiny package with:
install.packages("shiny")
To initialize a new Shiny app, click File > New File > Shiny Web App. Give your app a name and choose a location. RStudio will create a directory containing ui.R and server.R with some template code to get you started.
Designing the User Interface
Open ui.R. This script controls the layout and appearance of your app. The template generated has a basic layout using Shiny‘s core UI functions:
fluidPage(
titlePanel("My Shiny App"),
sidebarLayout(
sidebarPanel(),
mainPanel()
)
)
This uses the fluidPage layout with a sidebar and main area. Within these you specify the UI components for your app.
Some key UI elements:
- fluidRow and column for organizing content into rows and columns
- sliderInput for selecting numeric values with a slider
- selectInput for selecting values from a dropdown
- textInput for entering free text
- checkboxInput and checkboxGroupInput for on/off toggles
- radioButtons for selecting a single item from a list
- dateInput or dateRangeInput for selecting dates
- actionButton for clickable buttons
See the Shiny widgets gallery for the complete list of input controls.
You refer to inputs in server.R by their inputId. For outputs, use the *Output functions and give them an outputId that is used to render them in ui.R.
Here‘s a simple UI providing inputs to select variables from the mtcars dataset and a text output to show the first few rows:
fluidPage(
titlePanel("Model Builder"),
sidebarLayout(
sidebarPanel(
selectInput("x", "Predictor:",
choices = names(mtcars)),
selectInput("y", "Outcome:",
choices = names(mtcars))
),
mainPanel(
verbatimTextOutput("preview")
)
)
)
Writing the Server Logic
Open server.R. This is where the meat of your app logic lives. The core of the script is a function that takes an input and output as arguments:
function(input, output) {
# app logic here
}
To access the current value of an input, use input$ followed by the inputId, like input$x.
Reactivity is a key concept in Shiny. Reactive values re-execute automatically when their inputs change. Use reactive({}) to create a reactive expression and wrap it in a render* function to generate output.
Here‘s the server logic for the UI above to preview the selected data:
function(input, output) {
dataset <- reactive({
mtcars[, c(input$x, input$y)]
})
output$preview <- renderPrint({
head(dataset())
})
}
This creates a reactive dataset based on the user‘s x and y selections and renders a text preview. Note the use of {{ }} to access the reactive data.
To run the app, click "Run App" in the upper right of the RStudio window. The app will launch in your default browser. As you change the inputs, you‘ll see the preview update reactively. Congratulations, you just built your first Shiny app!
Building the Model
Now let‘s expand the app to actually fit a model based on the selected variables and parameters. We‘ll give the user a few algorithm options and let them tune the parameters.
Update ui.R with radio buttons to select the algorithm type and sliders to control model parameters:
sidebarPanel(
selectInput("x", "Predictor:",
choices = names(mtcars)),
selectInput("y", "Outcome:",
choices = names(mtcars)),
radioButtons("type",
"Algorithm:",
choices = c("Linear" = "lm",
"Random Forest" = "rf")),
sliderInput("fraction",
"Fraction of data for training:",
min = 0.1, max = 0.9,
value = 0.7, step = 0.1),
conditionalPanel(
condition = "input.type == ‘rf‘",
sliderInput("mtry",
"Number of variables to sample:",
min = 1, max = 10, value = 2)
)
)
This uses a conditional panel to only show the mtry slider when random forest is selected.
In server.R, create reactive expressions to filter the data, split into train/test sets, and fit the selected model:
dataset <- reactive({
data <- mtcars[, c(input$x, input$y)]
data[complete.cases(data),]
})
model <- eventReactive(input$update, {
req(input$type, input$fraction)
train_index <- createDataPartition(
dataset()[[input$y]],
p = input$fraction,
list = FALSE
)
train <- dataset()[train_index,]
test <- dataset()[-train_index,]
switch(input$type,
lm = lm(formula(paste0(input$y, "~", input$x)),
data = train),
rf = randomForest(formula(paste0(input$y, "~", input$x)),
data = train,
mtry = input$mtry)
)
})
And render the model summary as text output:
output$model <- renderPrint({
req(model())
summary(model())
})
Assessing Performance
To evaluate the model, we‘ll generate predictions on the test set and visualize performance metrics.
Add tabset panels to the UI for the model summary and performance:
mainPanel(
tabsetPanel(
tabPanel("Model", verbatimTextOutput("model")),
tabPanel("Performance",
plotOutput("roc"),
plotOutput("confusion"))
)
)
And calculate the predictions and metrics in server.R:
predictions <- eventReactive(input$update, {
req(model())
test <- dataset()[-train_index,]
predict(model(), newdata = test)
})
output$roc <- renderPlot({
roc <- roc(test[[input$y]], predictions())
plot(roc, main = "ROC Curve")
})
output$confusion <- renderPlot({
actual <- factor(test[[input$y]] > 0.5, levels = c(FALSE, TRUE))
predicted <- factor(predictions() > 0.5, levels = c(FALSE, TRUE))
xtab <- table(predicted, actual)
fourfoldplot(xtab, color = c("#CC6666", "#99CC99"),
conf.level = 0, margin = 1, main = "Confusion Matrix")
})
This generates an ROC curve and confusion matrix comparing the predictions to the actual outcomes.
Making New Predictions
Finally, let‘s allow the user to input new data and get predictions from the model.
Add a new tab to the UI for manual entry:
tabPanel("Predict",
fluidRow(
textInput("new_x", "Enter new value for predictor variable:")
),
fluidRow(
verbatimTextOutput("predicted")
)
)
And use the model to generate predictions on the new data point:
output$predicted <- renderText({
req(model(), input$new_x)
x <- as.numeric(input$new_x)
y <- predict(model(), newdata = data.frame(input$x = x))
paste0("Predicted ", input$y, ": ", round(y, 2))
})
The final app lets users interactively build a model, evaluate its performance, and make predictions on new data – all without writing a single line of code themselves!
Deploying Your App
Once your app is working locally, you‘ll probably want to share it with others. The easiest way is to use shinyapps.io, a hosted service from RStudio. Sign up for a free account, then click the "Publish" button in RStudio and follow the prompts. Your app will deploy to a public URL that you can share with anyone.
For more advanced use cases, you can set up your own Shiny Server or RStudio Connect instance.
Learn More
This example just scratches the surface of what‘s possible with R Shiny. To learn more, check out these resources:
- Shiny official tutorials
- Mastering Shiny book by Hadley Wickham
- How to Start with Shiny online course
- Shiny Examples and Gallery
You can also find the complete code for the app developed in this article on GitHub.
Happy Shiny app building!