Chapter 6 Creating Web Apps using Shiny
(Computer Lab 4B)

To conclude our exploration of the different data visualisation and interactive content creation options R offers, we will take a brief look at the Shiny R package (Chang et al. 2021) in Computer Lab 4B. Using this package, we can create an interactive web app, all within R.

Don’t worry, you don’t need to have any prior knowledge in other coding languages, nor a background in web development. Now that we can do some coding in R, we should be able to tackle Shiny.

We won’t be able to cover everything Shiny-related in the one lab, but we hope to provide a taste of the potential that Shiny offers.

We strongly recommend that you read through this section before starting computer lab 4B. You will also benefit from having this page open while working through the lab.

Note: We suggest finishing the previous labs before reading any further.

6.1 Shiny Introduction

Shiny is an exceptional web application framework for R, and is surprisingly easy to learn (but like most things, difficult to master). To use Shiny in R, we first have to install the shiny R package, just like all the other R packages we have used so far.

Run the code below to install and load Shiny in R.

install.packages("shiny")
library(shiny)

6.1.1

Shiny has several built-in examples - let’s take a look at one of these now. Run the following code:

runExample("01_hello")

A new window should appear with a preview of the web app - take a look at the different elements, and try moving the slider (it should feel familiar after our work in the previous labs).

You will have noticed that by moving the slider, we are dynamically changing the number of bins used when displaying the histogram. This responsiveness is coded into the web app, using R code. Let’s take a look at the composition of this R code now.

6.2 Shiny App Code Structure

Shiny apps consist of three components:

  • A user-interface object (ui)
  • A server function (server)
  • A call to the shinyApp function

The ui object contains the source code which Shiny uses to prepare what the end-users of the web app see. In other words, this file controls the appearance and layout of the Shiny app. In the example Shiny web app from 6.1.1, the changes in the slider as we change the number of histogram bins are handled by the source code in the ui object.

The server function contains the R code which is used as a blueprint/set of instructions on how your computer should actually build your app. For example, the server function for the 6.1.1 example Shiny web app contains the R code to produce the histogram.

In previous iterations of Shiny, these two components needed to be in separate files, but now all Shiny apps can be contained within a single script, app.R, which makes life easier!6

Every Shiny app will have this structure: an app.R file, containing a ui object and a server function.

6.2.1

Before we talk about the shinyApp function, let’s take a look at the ui object code for the example Shiny web app from 6.1.1:

# Define UI for app that draws a histogram ----
ui <- fluidPage(

  # App title ----
# 0  
  titlePanel("Hello Shiny!"),

  # Sidebar layout with input and output definitions ----
# 1
  sidebarLayout(

    # Sidebar panel for inputs ----
# 2
    sidebarPanel(

      # Input: Slider for the number of bins ----
# 3
      sliderInput(inputId = "bins",
                  label = "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)

    ),

    # Main panel for displaying outputs ----
# 4
    mainPanel(

      # Output: Histogram ----
# 5
      plotOutput(outputId = "distPlot")

    )
  )
)

Note we have added commented numbers (i.e. 0, 1, 2, 3, 4 and 5) to the different sections of the code.

Let’s break down these different sections, referring to each numbered section in turn.

  1. The titlePanel function allows us to specify the title of our app.
  2. The sidebarLayout function specifies the appearance of the app, splitting the display into a sidebar and a main area (the sidebar is half the width of the main area by default).
  3. The sidebarPanel function typically contains functions or arguments that specify the details of what goes in the sidebar section of the app.
  4. In this example, the sliderInput function is used, to add a slider in the sidebar for the number of bins in the histogram (you can see that the code is specifying that between 1 and 50 bins are allowed to be chosen).
  5. Now that we have finished specifying the layout and appearance of the sidebar, we use the mainPanel function to specify that we are now working on the main area of the app.
  6. We can see that R is being told to put the distPlot plot in the main panel.

All of these functions are wrapped within the fluidPage function, which we don’t need to worry about just yet.

6.2.2

What about distPlot? Why are we using something that hasn’t been defined?

To answer this, let’s take a look now at the corrsponding server function.

Note that once again, we have added commented numbers to the different sections of the code.

# Define server logic required to draw a histogram ----
# 1
server <- function(input, output) {

  # Histogram of the Old Faithful Geyser Data ----
  # with requested number of bins
  # This expression that generates a histogram is wrapped in a call
  # to renderPlot to indicate that:
  #
  # - It is "reactive" and therefore should be automatically
  #    re-executed when inputs (input$bins) change
  # - Its output type is a plot
  
# 2
  output$distPlot <- renderPlot({

# 3  
    x    <- faithful$waiting
    bins <- seq(min(x), max(x), length.out = input$bins + 1)

# 4 
    hist(x, breaks = bins, col = "#75AADB", border = "white",
         xlab = "Waiting time to next eruption (in mins)",
         main = "Histogram of waiting times")

    })

}
  1. In brief, the server function performs some calculations and produces a histogram, with a number of bins that can be modified by the end-user (with the modification options specified in the ui object above).
  2. The output of the renderPlot function is assigned to the output object named distPlot.
  3. This renderPlot function contains some arguments which are used to specify the details used for the plot.
  4. These details are used within the hist function, to produce a histogram - and the results are passed, via the renderPlot function, to the distPlot object.

So, the name distPlot was arbitrary - any name could have been chosen. The important thing is to ensure that the names we use for any output we want shown in our web app are identical across our ui object and server function code.

6.2.3

Once we are happy with the code for our web app, we need to create it!

The code below shows the general layout for a Shiny app. Note that we must begin by loading the shiny package, then define our ui object and server function, and finally finish with using the shinyApp function. Within the shinyApp function, we must specify the ui object and server function we are pairing together to produce our app.

library(shiny)

# See the code chunks above for details on ui and server
ui <- ...

server <- ...

shinyApp(ui = ui, server = server)

6.3 Creating a Shiny App

To create a Shiny app, we first need to write our app.R script, and then save it in a new directory (e.g. a new folder) within our current working directory.

For example, I could save my app.R script to a new directory called my_data_science_shiny_app (which is within my current working directory).

Note: If you need a refresher on changing working directories, check the code chunk below:

# Your current working directory can be checked by running the code
getwd()
# You can change your working directory using several methods - one of the easiest is:
# Navigate to the menu bar at the top of the RStudio GUI, and click
# Session -> Set Working Directory -> Choose Directory...
# and go from there

If I would now like to run this app, I can do so by using the runApp function, as follows:

library(shiny)
runApp("my_data_science_shiny_app") 
# The directory name must be enclosed within quotation marks

Note that it is good practice to have a separate directory for each of your Shiny apps.

In Computer Lab 4B, we will develop a custom Shiny app - by reading through this content first, you should now be well prepared to tackle this challenge.

6.4 Publishing a Shiny App

The easiest way to share your Shiny app with others is to simply send them your app.R script (and associated files). However, this assumes that they have R and know how to use it.

If you would like instead to share your Shiny app as an online web page, then it can be accessed by anyone with the internet. The simplest option for this is to host your app on RStudio’s Shiny app hosting service shinyapps.io.

Note: If you are interested in doing this, make sure you select the Free option, which will allow you to host up to 5 apps free of charge.

While there are alternatives to this option, they require additional steps, and more advanced coding and IT skills which we don’t cover in this subject.

References

Chang, Winston, Joe Cheng, JJ Allaire, and Carson Sievert et al. 2021. shiny: Web Application Framework for R. https://shiny.rstudio.com/.
RStudio Team. 2020. RStudio: Integrated Development Environment for R. Boston, MA: RStudio, PBC. http://www.rstudio.com/.
Wickham, Hadley. 2020. Mastering Shiny. O’Reilly Media. https://mastering-shiny.org/.

  1. Note: You can still create Shiny apps with separate ui.R and server.R files, but for this subject we will focus on single-file apps.↩︎