Shiny and R: How to Add Themes and Customize Error Messages

Michael Grogan
Share

R Shiny themes and error messages

The purpose of Shiny is to provide an intuitive and user-friendly interface to R. R is a highly popular statistical environment for doing heavy data analysis and constructing statistical models, and therefore is highly popular among data scientists. However, for a user with a non-coding background, using R to conduct such analysis can become quite intensive. This is where Shiny Web Apps come in. Essentially, Shiny allows for a more intuitive graphical user interface that is still capable of conducting sophisticated data analysis — without the need for extensive coding on the part of the end user.

In my article on using Shiny with R and HTML, I illustrated how an interactive web application can be created to conduct analysis without the need for direct manipulation of code. In this article, I’ll use a slightly different model to illustrate how the Shiny environment can be customized to work with the end user in a more intuitive fashion. Essentially, the goal of this article is to illustrate how a user can:

  1. Build an application by linking the UI and server side
  2. How to customize the themes available in the Shiny Themes library
  3. Implement error messages in order to provide guidance to an end user on how to use a particular program

The program itself that is developed for this tutorial is quite basic: a slider input allows the user to manipulate a variable within the program by means of reactivity, which causes instantaneous changes in the line plot output that is developed by means of reactivity.

This inherent function gives Shiny a significant advantage over using R code as a stand-alone. Traditionally, in order to analyze the change in a particular variable, the code must be manipulated directly (or the data from which the code is reading), and this can ultimately become very inefficient. However, Shiny greatly speeds up this process by allowing the user to manipulate the variables in a highly intuitive manner, and changes are reflected instantly.

However, the whole purpose of Shiny is to make an R Script as interactive as possible. In this regard, the user will want to be able to add features to the program that go well beyond reactivity. Two such aspects of this that I will discuss in this tutorial are:

  1. Using shinythemes in order to customize the appearance of our Shiny appearance
  2. Constructing a validate() function in order to display an alert once variables are manipulated in a certain manner

Shiny Themes

In the UI of our original program, we did not specify a theme, and therefore ended up with quite a basic (default Bootstrap) view of our output:

default Shiny app view

When we defined the shinyUI(fluidPage(…)) function, we didn’t specify a theme. In this instance, we’re going to specify several of the themes available from the Shiny Themes package.

After we’ve specified shinyUI(fluidPage(…)), we’re also specifying our theme as follows:

shinyUI(fluidPage(theme = shinytheme("cyborg")

the cyborg theme

From the above, we see that selecting the Cyborg theme gives our web app a dark background. As another example, let’s now select the Spacelab theme and see what we come up with:

the spacelab theme

These themes demonstrate more levels of customization depending on the other attributes in the Shiny code, such as additional buttons, tabs, etc. Feel free to experiment with the other themes at the RStudio GitHub account and see what you come up with!

validate() function

The validate function is an indispensable tool when it comes to working with Shiny code. Essentially, validate allows for an alert message to be triggered when a certain part of the Shiny program is manipulated.

In this particular instance, I discuss how we can use the validate and need functions to trigger an alert message when we manipulate the slider in our program.

The program itself, as last time, is quite basic in terms of its function. Essentially, our Shiny program produces a value on the X-axis between 1 and 100 depending on that selected by the slider.

We are then using the corresponding y-value to produce an error message whenever the calculated slope falls below 5 — that is, at a value of 29 or greater. Note that the program is not calculating slope directly, but instead the user in this instance is using the value of 29 as the cutoff point for this slope based on manual calculation.

Within the user interface, we specify the validation trigger under our shinyUI as follows:

shinyUI(fluidPage(theme = shinytheme("spacelab"),
tags$head(
  tags$style(HTML("
    .shiny-output-error-validation {
    color: red;
    }
    "))
),

Under the server, we specify the validate and need commands under the input-output function:

function(input, output) {
  output$algebra < - renderPlot({
    validate(
      need(input$lambda <= 28, "A value set at 29 or above produces a slope below 5. Please set a value below 29.")
    )

Full Program Code

The UI and Server code as a whole is displayed below:

UI

#Load libraries
library(shiny)
library(shinythemes)


#Define Shiny theme and specify shiny-output-error-validation
shinyUI(fluidPage(theme = shinytheme("spacelab"),


tags$head(
  tags$style(HTML("
    .shiny-output-error-validation {
    color: red;
    }
    "))
),


sidebarLayout(
  sidebarPanel(
    sliderInput("lambda",
      "Number of data points:",
      min = 1,
      max = 100,
      value = 1)
),


mainPanel(
  h3("Slope of a line", style = "font-family: 'Jura'; color: blue; font-size: 32px;"),
  HTML("<p>Excluding slope below 5 where y = 2x + 3"),
  plotOutput("algebra")
)
)
))

Server

#Load libraries
library(shiny)
library(ggplot2)
library(scales)


#Define validate function
function(input, output) {
  output$algebra <- renderPlot({
    validate(
      need(input$lambda <= 28, "A value set at 29 or above produces a slope below 5. Please set a value below 29.")
    )


#Define y as 2x+3 (using lambda to represent x variable)
    n <- 1:100
    lambda <- seq(min(n), max(n), length.out = input$lambda)
    plot((2*lambda)+3, type = "o", col = 'blue',
         fg = 'blue', xlab= "X (number of data points)", ylab = "Y = 2x+3")
  })
}

As a quick recap, we run the program by:

  • Opening R Studio and selecting the New IconShiny Web App

opening a new Shiny app

  • We see that we then have an option to choose single file (with both UI.R and server.R), or a multiple file (where UI.R and server.R are in separate scripts). We will use multiple file here.

choosing multiple file

  • Now, we paste the above UI and server codes into their respective sections and run the program by selecting Run App.

running the app

We see that our line graph grows in data points on the x-axis depending on how we manipulate the slider. However, you’ll notice that once the slider is moved to a value of 29 or above, the error message is displayed, “A value set at 29 or above produces a slope below 5. Please set a value below 29”.

error message display

Displaying of such error messages can be highly useful when a developer wishes to direct an external user on the use of such a program. For instance, if it was the case that no error messages were to be displayed, then the user has free rein to make inputs into the program that might not necessarily be suitable. In this way, the developer can give further safeguards against inadvertent inputs by an external user, while doing this solely in R code leaves the inputs open to manipulation.

For instance, the Shiny website itself gives an example of how the validate function can also be applied to a list. The UI and server produce a histogram as output, but the program produces an error message when a particular dataset is selected in the list. In this way, the validate command does exactly that — validates a particular input, while the need function is what allows us to personalize the same by customizing our error message — that is, input$lambda <= 28, “A value set at 29 or above produces a slope below 5. Please set a value below 29.”

Moreover, while we only specified one error message, we could potentially specify multiple. For instance, let’s now suppose that we want to display an additional error message when the slider goes above a value of 35:

function(input, output) {
  output$algebra <- renderPlot({
    validate(
      need(input$lambda <= 28, "A value set at 29 or above produces a slope below 5. Please set a value below 29."),
      need(input$lambda <= 35, "Your slider is now at a value greater than 35!")
    )

Using an additional need function in the server code, manipulating the slider to a value above 35 means that we now display the additional error message, “Your slider is now at a value greater than 35!”

highlighted error message

Conclusion

In this article, we’ve seen how to manipulate the design of our Shiny app using Shiny Themes, and learned how to apply filters to the parameters of our code and display error messages when certain conditions have been breached.

Ultimately, the focus of Shiny is in allowing for a far greater user-friendly and intuitive experience in conducting analysis than would be possible using R alone, and also minimizes risk of user input errors by properly specifying the parameters for a particular program.