Developing Reactive R Shiny Dashboards for Data Visualisation and Predictive Analytics

RP Digitalisation Challenge 2023

Conducted at HPI Lab E43A/B/C on Tuesday 11th April 2023, 2:00pm - 4:00pm

ATTENDANCE TAKING

LEARNING OUTCOMES FOR THIS SESSION OF THE DIGITIZATION CHALLENGE

At the end of this Digitization Challenge Session, you would be able to:

  1. Describe the various components of the R Studio Integrated Development Environment |IDE| and how to input functions, variables and arguments in the console to generate output.
  2. Describe the architecture of a Shiny App with reference to the User Interface and Server functions.
  3. Specify the code that builds the UI of a Shiny App, by defining the layout, input and output controls.
  4. Develop an app that contains reactive programming, embedded in the UI inputs, render*() functions as well as UI outputs.
  5. Adapt the R Shiny App interface to incorporate different types of ggplot2 type visualisations, which include reactive inputs and expressions.
  6. Customise the UI of an R Shiny App using different HTML interface builder functions, layout panels, tabset panels and themes.
  7. Publish your R Shiny App on the hosting services such as the shinyapps.io server.

SETTING UP YOUR R STUDIO CLOUD ACCOUNT

Please follow the steps outlined below to set up your R Studio Cloud Account, which will be used for this session.

Congratulations, your R Studio Cloud Account is now ready !

THE R STUDIO IDE WORKSPACE COMPONENTS

The R Studio IDE Workspace consists of the following key components

DATA TYPES AND ASSIGNMENT OF VARIABLES IN R

CREATING AND MANAGING VECTORS IN R

LOADING THE PACKAGES AND DATA REQUIRED FOR THIS SESSION IN R

Loading the R Packages

This is the code for installation of Pacman which is used to unpack all packages required in this lesson.

install.packages("pacman",repos = "http://cran.us.r-project.org")
## package 'pacman' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\aaron_chen_angus\AppData\Local\Temp\Rtmp8Cwwf8\downloaded_packages

We will then proceed to load the packages required for this section

pacman::p_load(pacman, psych, rio, tidyverse, ggplot2, ggridges, devtools, vioplot, dplyr, ggwordcloud, ggforce, gridExtra, kableExtra, shiny)

Loading the Dataset

For this session, we will be using the movies dataset, which combines data from two websites: the Internet Movie Database, commonly known as IMDB, and Rotten Tomatoes. The observations are a random sample of 651 movies released in the US between 1970 and 2014.

GitHub Link for Movies Dataset (in csv) : https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

Check on the output and hence the integrity of the loaded data by reading the column names. You can also see that the data consists of the following fields

movies %>% colnames()
##  [1] "X"                "title"            "title_type"       "genre"           
##  [5] "runtime"          "mpaa_rating"      "studio"           "thtr_rel_date"   
##  [9] "thtr_rel_year"    "thtr_rel_month"   "thtr_rel_day"     "dvd_rel_date"    
## [13] "dvd_rel_year"     "dvd_rel_month"    "dvd_rel_day"      "imdb_rating"     
## [17] "imdb_num_votes"   "critics_rating"   "critics_score"    "audience_rating" 
## [21] "audience_score"   "best_pic_nom"     "best_pic_win"     "best_actor_win"  
## [25] "best_actress_win" "best_dir_win"     "top200_box"       "director"        
## [29] "actor1"           "actor2"           "actor3"           "actor4"          
## [33] "actor5"           "imdb_url"         "rt_url"

You can also use the following command to view a sample of 10 movies with all 35 fields in a table

kbl(movies[180:190, 1:35]) %>%
    kable_styling(fixed_thead = TRUE)
X title title_type genre runtime mpaa_rating studio thtr_rel_date thtr_rel_year thtr_rel_month thtr_rel_day dvd_rel_date dvd_rel_year dvd_rel_month dvd_rel_day imdb_rating imdb_num_votes critics_rating critics_score audience_rating audience_score best_pic_nom best_pic_win best_actor_win best_actress_win best_dir_win top200_box director actor1 actor2 actor3 actor4 actor5 imdb_url rt_url
180 180 Resident Evil Feature Film Action & Adventure 100 R Columbia Tristar Pictures 2002-03-15 05:00:00 2002 3 15 2002-07-30 04:00:00 2002 7 30 6.7 192052 Rotten 33 Upright 68 no no no no no no Paul W.S. Anderson Milla Jovovich Michelle Rodriguez Eric Mabius James Purefoy Martin Crewes http://www.imdb.com/title/tt0120804/ //www.rottentomatoes.com/m/resident_evil/
181 181 Top Gun Feature Film Drama 110 PG Paramount Pictures 1986-05-16 04:00:00 1986 5 16 1998-10-20 04:00:00 1998 10 20 6.9 211129 Rotten 54 Upright 83 no no no no no yes Tony Scott Tom Cruise Kelly McGillis Anthony Edwards Val Kilmer Tom Skerritt http://www.imdb.com/title/tt0092099/ //www.rottentomatoes.com/m/top_gun/
182 182 25th Hour Feature Film Drama 135 R Touchstone Pictures 2003-01-10 05:00:00 2003 1 10 2003-05-20 04:00:00 2003 5 20 7.7 146518 Certified Fresh 78 Upright 85 no no yes no no no Spike Lee Edward Norton Barry Pepper Philip Seymour Hoffman Rosario Dawson Anna Paquin http://www.imdb.com/title/tt0307901/ //www.rottentomatoes.com/m/25th_hour/
183 183 The Bad News Bears in Breaking Training Feature Film Comedy 100 PG Paramount Pictures 1977-07-08 04:00:00 1977 7 8 2002-02-12 05:00:00 2002 2 12 5.4 2239 Rotten 50 Spilled 39 no no no no no no Michael Pressman William Devane Jackie Earle Haley Clifton James Jimmy Baio Chris Barnes http://www.imdb.com/title/tt0075718/ //www.rottentomatoes.com/m/bad_news_bears_in_breaking_training/
184 184 Streets of Gold Feature Film Drama 95 R Live Home Video 1986-11-14 05:00:00 1986 11 14 NA NA NA NA 6.0 486 Rotten 31 Spilled 44 no no no no no no Joe Roth Klaus Maria Brandauer Adrian Pasdar Richard Pasdar Wesley Snipes Angela Molina http://www.imdb.com/title/tt0092022/ //www.rottentomatoes.com/m/streets_of_gold/
185 185 The Mod Squad Feature Film Drama 92 R MGM 1999-03-26 05:00:00 1999 3 26 1999-08-24 04:00:00 1999 8 24 4.1 7658 Rotten 4 Spilled 17 no no no no no no Scott Silver Claire Danes Giovanni Ribisi Omar Epps Josh Brolin Dennis Farina http://www.imdb.com/title/tt0120757/ //www.rottentomatoes.com/m/mod_squad/
186 186 Where the Heart Is Feature Film Drama 107 R Touchstone Pictures 1990-01-01 05:00:00 1990 1 1 2003-06-03 04:00:00 2003 6 3 6.1 1268 Rotten 11 Spilled 58 no no no no no no John Boorman Dabney Coleman Uma Thurman Joanna Cassidy Crispin Glover Suzy Amis http://www.imdb.com/title/tt0100924/ //www.rottentomatoes.com/m/1028561-where_the_heart_is/
187 187 Battlefield Earth Feature Film Action & Adventure 118 PG-13 Warner Bros. Pictures 2000-05-12 04:00:00 2000 5 12 2001-01-16 05:00:00 2001 1 16 2.4 64119 Rotten 3 Spilled 11 no no yes no no no Roger Christian John Travolta Barry Pepper Forest Whitaker Kim Coates Richard Tyson http://www.imdb.com/title/tt0185183/ //www.rottentomatoes.com/m/battlefield_earth/
188 188 Osmosis Jones Feature Film Comedy 95 PG Warner Bros. Pictures 2001-08-10 04:00:00 2001 8 10 2001-11-13 05:00:00 2001 11 13 6.2 24678 Rotten 55 Spilled 41 no no no no no no Bill Murray Bill Murray Chris Rock Laurence Fishburne David Hyde Pierce William Shatner http://www.imdb.com/title/tt0181739/ //www.rottentomatoes.com/m/osmosis_jones/
189 189 Never Cry Wolf Feature Film Drama 105 PG Disney 1983-01-01 05:00:00 1983 1 1 2000-02-22 05:00:00 2000 2 22 7.6 6114 Fresh 100 Upright 85 no no no no no no Carroll Ballard Charles Martin Smith Brian Dennehy Zachary Ittimangnaq Samson Jorah Hugh Webster http://www.imdb.com/title/tt0086005/ //www.rottentomatoes.com/m/never_cry_wolf/
190 190 A Good Woman Feature Film Drama 93 PG Lions Gate Films 2006-02-03 05:00:00 2006 2 3 2006-06-13 04:00:00 2006 6 13 6.5 9399 Rotten 37 Spilled 49 no no no yes no no Mike Barker Helen Hunt Scarlett Johansson Tom Wilkinson Stephen Campbell Moore Mark Umbers http://www.imdb.com/title/tt0379306/ //www.rottentomatoes.com/m/good_woman/

WHAT IS A SHINY APP ?

Shiny is an R package that makes it easy to build interactive web apps straight from R. It combines the computational power of R with the interactivity of the modern web.

Here is an example of a Shiny App that you would build by the end of this session, allowing end users to navigate the dataset on movies that you have just loaded.

This will contain the following :

HOW DOES R SHINY WORK ?

Every Shiny app has a webpage that the user visits, and behind this webpage there is a computer that serves this webpage by running R.

When running your app locally, the computer serving your app is your computer.

When your app is deployed, the computer serving your app is a web server.

Each app is comprised of two components, a UI and a server.

The UI is ultimately built with HTML, CSS, and JavaScript. However, you as the Shiny developer do not need to know these languages. Shiny lets R users write user interfaces using a simple, familiar-looking API. However there are no limits to customization for advanced users who are familiar with these languages.

The server function contains the instructions to map user inputs to outputs.

ANATOMY OF A SHINY APP

Lets start by taking a look at the anatomy of a Shiny App.

Here is the code for the development of a simple app. You can copy it into your R Studio IDE workspace, select all of the code, and press CTRL + Enter on your keypad to preview the output.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  
  sidebarLayout(
    
    # Inputs: Select variables to plot
    sidebarPanel(
      
      # Select variable for y-axis
      selectInput(
        inputId = "y",
        label = "Y-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "imdb_rating"
      ),
      # Select variable for x-axis
      selectInput(
        inputId = "x",
        label = "X-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "critics_score"
      )
    ),
    
    # Output: Show scatterplot
    mainPanel(
      plotOutput(outputId = "scatterplot")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y)) +
      geom_point()
  })
}

# Create a Shiny app object ----------------------------------------------------

shinyApp(ui = ui, server = server)
## PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.

We will now go into the User Interface (UI) and Server Function as they are applied in the development of this app.

USER INTERFACE

In this section we’ll build the user interface of a simple app.

However, before we get into the weeds of building a user interface, let’s revisit the anatomy of a Shiny app.

Example

For example, if your app features a plot, the code for building that plot lies in the server function. However, the setup for the user defined inputs for the plot, as well as information on where physically on the app the plot should appear, are defined in the UI.

Here is the app we’ll work with in this section and the code that builds the UI of that app.

Since this is too much code to parse, we’ll explore individual components of the UI one by one.

fluidPage()

At the outermost layer of our UI definition we begin with the fluidPage() function.

The fluidPage() function creates a fluid page layout consisting of rows and columns. Rows make sure that elements in them appear on the same line. Columns within these rows define how much horizontal space each element should occupy.

Fluid pages scale their components in realtime to fill all available browser width, which means you, the app developer, don’t need to worry about defining relative widths for individual app components.

As always, for more information on arguments to this function, you can view the R function help by typing ?f luidPage in your R console or visiting the function reference page on the package website here


Layout

Next, we define the layout of our app with sidebarLayout().

Shiny includes a number of options for laying out the components of an application. The default layout, the one we’re using in our example app, is a layout with a sidebar, that you can define with the sidebarLayout() function.

This is a simple layout with a narrow sidebar for inputs and a wider main area for output.

Under the hood, Shiny implements layout features available in Bootstrap 2, which is a popular HTML/CSS framework. However the nice thing about working in Shiny is that no prior experience with Bootstrap is necessary.

To learn more about various layouts, I recommend reviewing the Application Layout Guide article at https://shiny.rstudio.com/.


Input Controls

Next we define our sidebar panel containing input controls.

This panel contains two dropdown menus created with the selectInput() function.

Let’s take a look at one of the selectInput widgets a little more closely.

Main Panel

The final component of our UI is mainPanel().

In this example provided, the main panel contains only one component, a plot output. We’ll talk about how this plot is built later on in this lesson.

SERVER FUNCTION

The key purpose of the server function is to define the relationship between inputs and outputs.

Here again is the app that we are working with in this module

In the earlier section, we showed you how to build the UI of this app, and also noted that each input was tagged with an inputId that can be used to refer to them in the server.

This is the server function code for this app

Once again there is a lot going on here to parse at once, so in the following sections we take a closer look at the function.

At the outermost layer

We define our server function which takes two arguments: an input and an output. Both of these are named lists.

The server function accesses inputs selected by the user to perform computations and specifies how outputs laid out in the UI should be updated.

output

Our simple app had only one output – a plot. So our server function contains the logic necessary to build this plot.

renderPlot()

The renderPlot() function specifies how the plot output should be updated. Let’s take a look at what is happening in the renderPlot() function first.

You may have noticed that this is none other than ggplot2 code which we covered in lesson 11.

One aspect of the syntax that might be new, however, is how the x and y variables are defined. They come from the input list that is built in the UI.

Inputs

Here is the relevant UI and server code.

Input x and y come from the selectInput() widgets, and map to the x and y arguments of the plot aesthetics.

Rules of server functions

There are three rules of building server functions:

  1. Always save objects to display to the named output list, i.e. something of the form output$xx, where xx is the plot you want to display.

  2. Always build objects to display with one of the render*() functions, like we built our plot with renderPlot().

  3. Use input values from the named input list, with input$xx.

Output types

Just like various inputs, Shiny also provides a wide selection of output types each of which works with a render function.

For example, in our app we used the renderPlot() function to build our reactive plot (we’ll get to what I mean by reactive in a second) and laid out the plot with the plotOutput() function.

Shiny knows to match these two together as they use the same outputID, scatterplot.

Reactivity

Let’s also briefly discuss reactivity, which we will go into further details in a subsequent section.

It’s easy to build interactive applications with Shiny, but to get the most out of it, you’ll need to understand the reactive programming scheme used by Shiny.

In a nutshell Shiny automatically updates outputs, such as plots, when inputs that go into them change.

Putting all the pieces together

The last component of a Shiny app is aptly named shinyApp() function, which puts the UI and the server pieces together to create a Shiny app object.

ADDING A THIRD DIMENSION TO THE R SHINY APP SCATTERPLOT

Let us now take a look at a further development of the R Shiny App Scatterplot derived from the movies data, which now adds a third dimension to the variables, that being color (spelt the American way because R is coded this way)

Similar to what you did earlier, copy the code into your R Studio IDE, highlight and press CTRL + Enter to preview the output.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  sidebarLayout(
    
    # Inputs: Select variables to plot
    sidebarPanel(
      
      # Select variable for y-axis
      selectInput(
        inputId = "y",
        label = "Y-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics score" = "critics_score",
          "Audience score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "audience_score"
      ),
      
      # Select variable for x-axis
      selectInput(
        inputId = "x",
        label = "X-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics score" = "critics_score",
          "Audience score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "critics_score"
      ),
      
      # Select variable for color
      selectInput(
        inputId = "z",
        label = "Color by:",
        choices = c(
          "Title type" = "title_type",
          "Genre" = "genre",
          "MPAA rating" = "mpaa_rating",
          "Critics rating" = "critics_rating",
          "Audience rating" = "audience_rating"
        ),
        selected = "mpaa_rating"
      )
    ),
    
    # Output: Show scatterplot
    mainPanel(
      plotOutput(outputId = "scatterplot")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(
      x = input$x, y = input$y,
      color = input$z
    )) +
      geom_point()
  })
}

# Create a Shiny app object ----------------------------------------------------

shinyApp(ui = ui, server = server)

REACTIVE FLOW

The concept of reactivity is key to Shiny App development.

Suppose you have a sliderInput in your app with the inputId of alpha. The value of this input is stored in input$alpha.

So when the user moves around the slider, the value of the alpha input is updated in the input list.

Reactivity 101

Reactivity automatically occurs when an input value is used to render an output object, i.e. in the server function below the plot is re-rendered when the value of input alpha changes based on user input. You, as the app developer, do not need to write code that says “Update the plot every time the value of input alpha changes”, Shiny automatically takes care of this for you in the render*() function.

Reactive flow

Here is a roadmap of the reactive flow in Shiny.

The user selects an input, this input goes through some expression in the server, and an output is rendered. Each time the user changes their input selection, the expression that generates the output will automatically re-execute, and the relevant output will be re-rendered based on the new value of the input.

In a Shiny application, there’s no need to explictly describe the relationships between inputs and outputs and tell R what to do when each input changes, Shiny automatically handles these details for you.

Build a Simple Reactive Widget

The following is code for a new input widget, a sliderInput, that controls the transparency of the plotted points.

This widget should have the ID alpha and its values should range between 0 and 1. You can decide what the displayed label and initial value of the slider should be.

Similar to before, copy the code into your R Studio IDE, highlight and press CTRL + Enter to preview the output.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "y",
        label = "Y-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "audience_score"
      ),
      
      selectInput(
        inputId = "x",
        label = "X-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "critics_score"
      ),
      
      sliderInput(
        inputId = "alpha",
        label = "Alpha:",
        min = 0, max = 1,
        value = 0.5
      )
    ),
    
    mainPanel(
      plotOutput(outputId = "scatterplot")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y)) +
      geom_point(alpha = input$alpha)
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

UI INPUTS

The goal of this section is to build familiarity with a few UI input functions.

Shiny provides a wide selection of input widgets. The Shiny cheatsheet is a great place to see a list of them all at once.

Once you know which one you want to use, you can find out more about it in the package documentation.

CHECKBOXINPUT

Let’s start with a checkboxInput().

Suppose we want to add checkbox input to our app to specify whether the data plotted should be shown in a data table. We need to make three modifications to our app to accomplish this.

  1. In the ui: Add an input widget that the user can interact with to check/uncheck the box.
  2. In the ui: Add an output to the UI defining where the data table should appear.
  3. In the server function: Add a reactive expression that creates the data table if the checkbox is checked. We’ll go through these steps one by one.

1. ui: Add an input widget that the user can interact with to check/uncheck the box

# Show data table
checkboxInput(inputId = "show_data",
              label = "Show data table", 
              value = TRUE)

Watch for commas!

A cautionary tale before we move on – watch for your commas! Remember that this widget definition goes in the sidebarPanel(). In this panel we separate out widget with commas.

For example:

2. ui: Add an output to the UI defining where the data table should appear.

mainPanel(
  # Show scatterplot
  plotOutput(outputId = "scatterplot"), 
  # Show data table
  dataTableOutput(outputId = "movestable")
)

The second step was to add an output to the UI defining where the data table should appear. Note that for this we’re using the dataTableOutput() function.

This function takes one argument, the outputId. Again, you can define to be anything we want, but short and informative names are the best.

3. server: Add a reactive expression that creates the data table if the checkbox is checked.

# Print data table if checked 
output$moviestable <- renderDataTable({
  if(input$show_data){
    DT::datatable(data = movies %>% select(1:7),
                  options = list(pageLength = 10),
                  rownames = FALSE)
  } 
})

Lastly, in our server, we describe how this table should be calculated. We use the renderDataTable() function to build this table.

Note that the first line of code in the function is an if statement, telling the app to only do this if input$show_data is TRUE. We also specify some other arguments to datatable(), mostly for cosmetic reasons.

Here is the resulting app, with the box checked:

and box unchecked:

Here is the code. You may copy the code into your R Studio IDE, highlight and press CTRL + Enter to preview the output.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(dplyr)
library(DT)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      # Select variable for y-axis 
      selectInput(inputId = "y", label = "Y-axis:",
                  choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
                  selected = "audience_score"),  
      # Select variable for x-axis
      selectInput(inputId = "x", label = "X-axis:",
                  choices = c("imdb_rating", "imdb_num_votes", "critics_score",  
                              "audience_score", "runtime"),
                  selected = "critics_score"),
      # Show data table 
      checkboxInput(inputId = "show_data",
                    label = "Show data table", value = TRUE)   
    ),
    
    mainPanel(
      # Show scatterplot
      plotOutput(outputId = "scatterplot"), 
      # Show data table
      dataTableOutput(outputId = "movestable")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  output$moviestable <- renderDataTable({
    if(input$show_data){
      DT::datatable(data = movies %>% select(1:7),
                    options = list(pageLength = 10),
                    rownames = FALSE)
    } 
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

RENDER*() FUNCTIONS

The goal of this section is to build familiarity with a few rendering functions.

Shiny provides a wide selection of output types, each of which works with a render function. We looked at the renderPlot() function before.

Now let’s take a look at the renderTable() function.

This is the app you’ve seen numerous times so far that we will use as our starting point.

And this is the final app that we want to achieve, with a summary table beneath the plot.

RENDERTABLE

So we want to add a summary table beneath the plot displaying summary statistics for a new variable we’ll create: score_ratio, the ratio of audience scores to critics scores.

We need to make four modifications to our app to accomplish this.

  1. Calculate the new variable
  2. In the ui: Add an input widget that the user can interact with to check boxes for selected title types.
  3. In the ui: Add an output defining where the summary tables should appear.
  4. In the server function: Add a reactive expression that creates the summary table. We’ll go through these steps one by one.

1. Calculate the new variable.

# Create new variable:
# ratio of critics and audience scores
movies <- movies %>%
  mutate(score_ratio = audience_score / critics_score)

First is creating the new variable, which we can do outside of the ui and the server so it’s calculated once when our app launches.

There are many ways one can create the new variable in R. We do so here using the mutate() function from the dplyr package.

2. ui: Add an input widget that the user can interact with to check boxes for selected title types.

# Subset for title types
checkboxGroupInput(inputId = "selected_title_type", 
                   label = "Select title type:", 
                   choices = levels(moves$title_type),
                   selected = levels(movies$title_type))

3. ui: Add an output defining where the summary tables should appear.

mainPanel(
  # Show scatterplot
  plotOutput(outputId = "scatterplot"), 
  # Show data table
  tableOutput(outputId = "summarytable")
)

We use the tableOutput() function for this. This function takes one argument, the outputId.

4. server: Add a reactive expression that creates the summary table.

Lastly, in the server, we describe how this table should be calculated with the renderTable() function.

output$summarytable <- renderTable(
  {
    movies %>%
      filter(title_type %in% input$selected_title_type) %>%
      group_by(mpaa_rating) %>%
      summarise(mean_score_ratio = mean(score_ratio), SD = sd(score_ratio), n = n())
  },
  striped = TRUE,
  spacing = "l",
  align = "lccr",
  digits = 4,
  width = "90%",
  caption = "Score ratio (audience / critics' scores) summary statistics by MPAA rating."
)

Note that the name of the output created by the render function should match the name we used for the output in the ui (summarytable).

The first argument is the expression that returns an R object in tabular form.

  {
    movies %>%
      filter(title_type %in% input$selected_title_type) %>%
      group_by(mpaa_rating) %>%
      summarise(mean_score_ratio = mean(score_ratio), SD = sd(score_ratio), n = n())
  }

Note that we wrap the expression with curly braces. The expression first filters for the selected title types. Since this is a user selection, the information is in the input list generated in the ui.

Then, the expression groups the data by MPAA rating, and then calculates summary statistics like means, standard deviations, and sample sizes for each level of MPAA ratings.

If we stopped here and didn’t include any of the following arguments, the app would look something like this:

But we want our table to look like this:

In order to achieve this look, we add additional arguments to our render* function.

striped = TRUE, spacing = "l", align = "lccr", digits = 4, width = "90%",
caption = "Score ratio (audience / critics' scores) summary statistics by MPAA rating."

ADD RENDERTEXT()

In this app, the user selects x and y variables for the scatterplot. We will extend the app to also include a textOutput which prints the correlation between the two selected variables as well some informational text.

In this code, we will attempt to

  1. Create the text to be printed using the paste() function: “Correlation = ____. Note: If the relationship between the two variables is not linear, the correlation coefficient will not be meaningful.”
  2. Place the text within the renderText() function, and assign to output text .
# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(dplyr)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "y",
        label = "Y-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "audience_score"
      ),
      
      selectInput(
        inputId = "x",
        label = "X-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "critics_score"
      )
    ),
    
    mainPanel(
      plotOutput(outputId = "scatterplot"),
      textOutput(outputId = "correlation")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y)) +
      geom_point()
  })
  
  # Create text output stating the correlation between the two ploted
  output$correlation <- renderText({
    r <- round(cor(movies[, input$x], movies[, input$y], use = "pairwise"), 3)
    paste0(
      "Correlation = ", r,
      ". Note: If the relationship between the two variables is not linear, the correlation coefficient will not be meaningful."
    )
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

Run the script in your R studio IDE to view and manipulate the output. You should see something like this :

UI OUTPUTS

We’ve seen UI outputs before, and in this section we dive deeper into the plotOutput() function to build an interactive graph.

Once again we’re going to start with this app.

And we’ll add functionality to the app so that movies corresponding to the selected points on the plot via brushing are displayed in a data table beneath the plot.

PLOTOUTPUT()

We need to make three modifications to our app to accomplish this.

  1. ui: Add functionality to plotOutput to select points via brushing.
  2. ui: Add an output defining where the data table should appear.
  3. server: Add a reactive expression that creates the data table for the selected points. Let’s go through these steps one by one.

1. ui: Add functionality to plotOutput to select points via brushing.

2. ui: Add an output defining where the data table should appear.

3. server: Add a reactive expression that creates the data table for the selected points.

BRUSHING

Here is how to create the output that was described in the previous section, with a brush used to select entries which will appear on the data table.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(dplyr)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  br(),
  
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "y", label = "Y-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "audience_score"
      ),
      
      selectInput(
        inputId = "x", label = "X-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "critics_score"
      )
    ),
    
    mainPanel(
      plotOutput(outputId = "scatterplot", brush = "plot_brush"),
      DT::dataTableOutput(outputId = "moviestable"),
      br()
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y)) +
      geom_point()
  })
  
  output$moviestable <- renderDataTable({
    brushedPoints(movies, brush = input$plot_brush) %>%
      select(title, audience_score, critics_score)
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

Run the script in your R studio IDE to view and manipulate the output. You should see something like this :

HOVERING

In addition to brushing, users can also interact with plots via hovering over them, which the following code will demonstrate.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(dplyr)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  br(),
  
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "y", label = "Y-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "audience_score"
      ),
      selectInput(
        inputId = "x", label = "X-axis:",
        choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
        selected = "critics_score"
      )
    ),
    
    mainPanel(
      plotOutput(outputId = "scatterplot", hover = "plot_hover"),
      dataTableOutput(outputId = "moviestable"),
      br()
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y)) +
      geom_point()
  })
  
  output$moviestable <- renderDataTable({
    nearPoints(movies, input$plot_hover) %>%
      select(title, audience_score, critics_score)
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

Run the script in your R studio IDE to view and manipulate the output. You should see something like this, with the data table displaying the selected movies and details as you hover over the section of the scatter plot :

DISPLAYING TEXT OUTPUTS

This code will develop an app where the user selects two variables and their relationship is visualized with a scatterplot, and averages of both variables are reported as well as the output of the linear regression predicting the variable on the y-axis from the variable in the x-axis.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(dplyr)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  sidebarLayout(
    
    sidebarPanel(
      
      selectInput(inputId = "y",
                  label = "Y-axis:",
                  choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
                  selected = "audience_score"),
      
      selectInput(inputId = "x",
                  label = "X-axis:",
                  choices = c("imdb_rating", "imdb_num_votes", "critics_score", "audience_score", "runtime"),
                  selected = "critics_score")
      
    ),
    
    # Output(s)
    mainPanel(
      plotOutput(outputId = "scatterplot"),
      textOutput(outputId = "avg_x"), # avg of x
      textOutput(outputId = "avg_y"), # avg of y
      verbatimTextOutput(outputId = "lmoutput") # regression output
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y)) +
      geom_point()
  })
  
  output$avg_x <- renderText({
    avg_x <- movies %>% pull(input$x) %>% mean() %>% round(2)
    paste("Average", input$x, "=", avg_x)
  })
  
  output$avg_y <- renderText({
    avg_y <- movies %>% pull(input$y) %>% mean() %>% round(2)
    paste("Average", input$y, "=", avg_y)
  })
  
  output$lmoutput <- renderPrint({
    x <- movies %>% pull(input$x)
    y <- movies %>% pull(input$y)
    print(summary(lm(y ~ x, data = movies)), digits = 3, signif.stars = FALSE)
  })
  
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

Run the script in your R studio IDE to view and manipulate the output. You should see something like this :

DOWNLOAD DATA WITH DOWNLOADBUTTON()

This code will use the downloadHandler() function in the server and downloadButton() or downloadLink() function in the UI. This would allow users to select and download the data in the fields they want.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(dplyr)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  sidebarLayout(
    
    sidebarPanel(
      
      radioButtons(inputId = "filetype",
                   label = "Select filetype:",
                   choices = c("csv", "tsv"),
                   selected = "csv"),
      
      checkboxGroupInput(inputId = "selected_var",
                         label = "Select variables:",
                         choices = names(movies),
                         selected = c("title"))
      
    ),
    
    mainPanel(
      HTML("Select filetype and variables, then hit 'Download data'."),
      downloadButton("download_data", "Download data")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  
  # Download file
  output$download_data <- downloadHandler(
    filename = function() {
      paste0("movies.", input$filetype)
    },
    content = function(file) { 
      if(input$filetype == "csv"){ 
        write_csv(movies %>% select(input$selected_var), file) 
      }
      if(input$filetype == "tsv"){ 
        write_tsv(movies %>% select(input$selected_var), file) 
      }
    }
  )
  
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

Run the script in your R studio IDE to view and manipulate the output. You should see something like this :

HERES A SAMPLE CODE WITH MULTIPLE REACTIVE ELEMENTS

Scan through the code and run it to see if you can identify the various reactive elements that have been added to the features of this app.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(tools)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "y",
        label = "Y-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics Score" = "critics_score",
          "Audience Score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "audience_score"
      ),
      
      selectInput(
        inputId = "x",
        label = "X-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics Score" = "critics_score",
          "Audience Score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "critics_score"
      ),
      
      selectInput(
        inputId = "z",
        label = "Color by:",
        choices = c(
          "Title Type" = "title_type",
          "Genre" = "genre",
          "MPAA Rating" = "mpaa_rating",
          "Critics Rating" = "critics_rating",
          "Audience Rating" = "audience_rating"
        ),
        selected = "mpaa_rating"
      ),
      
      sliderInput(
        inputId = "alpha",
        label = "Alpha:",
        min = 0, max = 1,
        value = 0.5
      ),
      
      sliderInput(
        inputId = "size",
        label = "Size:",
        min = 0, max = 5,
        value = 2
      ),
      
      textInput(
        inputId = "plot_title",
        label = "Plot title",
        placeholder = "Enter text to be used as plot title"
      ),
      
      actionButton(
        inputId = "update_plot_title",
        label = "Update plot title"
      )
    ),
    
    mainPanel(
      plotOutput(outputId = "scatterplot")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  new_plot_title <- eventReactive(
    eventExpr = input$update_plot_title,
    valueExpr = {
      toTitleCase(input$plot_title)
    }
  )
  
  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y, color = input$z)) +
      geom_point(alpha = input$alpha, size = input$size) +
      labs(title = new_plot_title())
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

Run the script in your R studio IDE to view and manipulate the output. You should see something like this :

THEMING

shinythemes

There are many other ways of customizing the look of your app, including using custom CSS. However one quick and easy way of changing the look is using the prebuilt themes in the shinythemes package.

In order to use one of these themes, you need to load the shinythemes package first. The package website has thumbnail images of each of the themes, but it can be difficult to tell exactly how the theme will look on your app.

Applying Different Themes

Pick a theme and apply to the existing app. See https://rstudio.github.io/shinythemes for more on theme options. Run the code below by changing the theme in the shinythemes line.

Possible options include

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(tools)
library(shinythemes)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(theme = shinytheme("united"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "y",
        label = "Y-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics Score" = "critics_score",
          "Audience Score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "audience_score"
      ),

      selectInput(
        inputId = "x",
        label = "X-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics Score" = "critics_score",
          "Audience Score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "critics_score"
      ),

      selectInput(
        inputId = "z",
        label = "Color by:",
        choices = c(
          "Title Type" = "title_type",
          "Genre" = "genre",
          "MPAA Rating" = "mpaa_rating",
          "Critics Rating" = "critics_rating",
          "Audience Rating" = "audience_rating"
        ),
        selected = "mpaa_rating"
      ),

      sliderInput(
        inputId = "alpha",
        label = "Alpha:",
        min = 0, max = 1,
        value = 0.5
      ),

      sliderInput(
        inputId = "size",
        label = "Size:",
        min = 0, max = 5,
        value = 2
      ),

      textInput(
        inputId = "plot_title",
        label = "Plot title",
        placeholder = "Enter text to be used as plot title"
      ),

      actionButton(
        inputId = "update_plot_title",
        label = "Update plot title"
      )
    ),

    mainPanel(
      tags$br(),
      tags$p(
        "These data were obtained from",
        tags$a("IMBD", href = "http://www.imbd.com/"), "and",
        tags$a("Rotten Tomatoes", href = "https://www.rottentomatoes.com/"), "."
      ),
      tags$p("The data represent", nrow(movies), "randomly sampled movies released between 1972 to 2014 in the United States."),

      plotOutput(outputId = "scatterplot")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  new_plot_title <- eventReactive(
    eventExpr = input$update_plot_title,
    valueExpr = {
      toTitleCase(input$plot_title)
    }
  )

  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y, color = input$z)) +
      geom_point(alpha = input$alpha, size = input$size) +
      labs(title = new_plot_title())
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

themeSelector()

A useful tool for browsing themes is the themeSelector() widget. To use this widget, simply add the widget to your app.

It can be inserted anywhere inside of the application, although if it is put inside a tab, it will be visible only when that tab is showing. I usually place it right underneath the fluidPage() definition.

This widget is to be used in development only. Once you decide on a theme, you should remove the widget and just define the theme you want using the shinytheme() function.

Live theme selector

If you want to quickly test out different themes with an application, you can simply add themeSelector() somewhere to the UI. This will add a select box which lets you choose the theme. It will change the theme without having to reload or restart your app. You can see the theme selector in action by running the code below.

# Load packages ----------------------------------------------------------------

library(shiny)
library(ggplot2)
library(tools)
library(shinythemes)

# Load data --------------------------------------------------------------------

movies <- read.csv(file = "https://raw.githubusercontent.com/aaron-chen-angus/S3729C-Lesson-Files/6a58d56d3d42231fb011af462db7efc01537e515/movies.csv", header = TRUE, sep = ",")

# Define UI --------------------------------------------------------------------

ui <- fluidPage(
  shinythemes::themeSelector(),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "y",
        label = "Y-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics Score" = "critics_score",
          "Audience Score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "audience_score"
      ),

      selectInput(
        inputId = "x",
        label = "X-axis:",
        choices = c(
          "IMDB rating" = "imdb_rating",
          "IMDB number of votes" = "imdb_num_votes",
          "Critics Score" = "critics_score",
          "Audience Score" = "audience_score",
          "Runtime" = "runtime"
        ),
        selected = "critics_score"
      ),

      selectInput(
        inputId = "z",
        label = "Color by:",
        choices = c(
          "Title Type" = "title_type",
          "Genre" = "genre",
          "MPAA Rating" = "mpaa_rating",
          "Critics Rating" = "critics_rating",
          "Audience Rating" = "audience_rating"
        ),
        selected = "mpaa_rating"
      ),

      sliderInput(
        inputId = "alpha",
        label = "Alpha:",
        min = 0, max = 1,
        value = 0.5
      ),

      sliderInput(
        inputId = "size",
        label = "Size:",
        min = 0, max = 5,
        value = 2
      ),

      textInput(
        inputId = "plot_title",
        label = "Plot title",
        placeholder = "Enter text to be used as plot title"
      ),

      actionButton(
        inputId = "update_plot_title",
        label = "Update plot title"
      )
    ),

    mainPanel(
      tags$br(),
      tags$p(
        "These data were obtained from",
        tags$a("IMBD", href = "http://www.imbd.com/"), "and",
        tags$a("Rotten Tomatoes", href = "https://www.rottentomatoes.com/"), "."
      ),
      tags$p("The data represent", nrow(movies), "randomly sampled movies released between 1972 to 2014 in the United States."),

      plotOutput(outputId = "scatterplot")
    )
  )
)

# Define server ----------------------------------------------------------------

server <- function(input, output, session) {
  new_plot_title <- eventReactive(
    eventExpr = input$update_plot_title,
    valueExpr = {
      toTitleCase(input$plot_title)
    }
  )

  output$scatterplot <- renderPlot({
    ggplot(data = movies, aes_string(x = input$x, y = input$y, color = input$z)) +
      geom_point(alpha = input$alpha, size = input$size) +
      labs(title = new_plot_title())
  })
}

# Create the Shiny app object --------------------------------------------------

shinyApp(ui = ui, server = server)

Other theming options

The bslib package provides tools for customizing Bootstrap themes directly from R, making it much easier to customize the appearance of Shiny apps & R Markdown documents.

The thematic package provides a functionality for simplified theming of ggplot2, lattice, and {base} R graphics as well as automatic theming of these plots within a Shiny app.

PUBLISHING YOUR R SHINY APP

You can publish your shiny app on the shinyapps.io website.

This is a free space for hosting your apps. However, the freemium version has several limitations.

Steps to publishing your app

Step 1: Open RStudio and create a new Shiny app:

Step 2: Give it a name (without space), choose where to save it and click on the Create button:

Step 3: In the same way as when you open a new R Markdown document, the code for a basic Shiny app is created. Run the app by clicking on the Run App button to see the result:

Step 4: The basic app opens, publish it:

Step 5: If it is your first Shiny app, the box “Publish From Account” should be empty. Click on “Add New Account” to link the shinyapps.io account you just created:

Step 6: Click on the first alternative (ShinyApps.io):

Step 7: Click on the link to your ShinyApps account:

Step 8: Click on the Dashboard button to log in into your account:

Step 9: Click on your name and then on Tokens:

Step 10: If this is your first app, there should be no token already created. Create one by clicking on the Add Token button. Then Click on the Show button:

Step 11: Click on the Show Secret button:

Step 12: Now the code is complete (nothing is hidden anymore). Click on the Copy to clipboard button:

Step 13: Copy the code and click on the OK button:

Step 14: Go back to RStudio, paste the code in the console and run it:

Your computer is now authorized to deploy applications to your shinyapps.io account.

Step 15: Go back to the window where you can publish your app, choose a title (without space) and click on the Publish button:

Step 16: After several seconds (depending on the how complex your app is), the Shiny app should appear in your internet browser:

Step 17: You can now edit the app (or replace the entire code by another of your app), and run the app again by clicking on the Run App button. For this illustration, I just added a link for more information in the side panel:

Step 18: Check that the modifications have been taken into account (the link appears in the side panel as expected) and republish your app:

Step 19: Click on the Publish button:

Step 20: Your app is live! You can now the link in your assignment and with everyone else, and they will be able to access it and interact with it:

REFERENCES

Mastering Shiny: Build Interactive Apps, Reports, and Dashboards Powered by R 1st Edition

by Hadley Wickham
online version : https://mastering-shiny.org/


citation : Wickham, H. (2021). Mastering Shiny: Build Interactive Apps, Reports, and Dashboards Powered by R. (1st ed). O’Reilly

ggplot2: Elegant Graphics for Data Analysis (Use R!)

by Hadley Wickham
online version : https://ggplot2-book.org/


citation : Wickham, H. (2016). ggplot2: Elegant Graphics for Data Analysis. (3rd ed). Routledge

R Graphics Cookbook, 2nd edition

by Winston Chang
online version : https://r-graphics.org/


citation : Chang, W. (2022). R Graphics Cookbook. (2nd ed). O’Reilly

A PRESENT FOR ALL SESSION ATTENDEES

Specially for all of the attendees of this session, I will be providing you with some sample apps that have been created with students in my S3729C Classes, with a focus on creating solutions for operations in Sports and Health.

Please feel free to download the source code in .R files, adpat and run the codes accordingly for your own purposes. Enjoy !

App 01 : BMI Calculator

App 02 : Rockport Walk Test VO2max Calculator

App 03 : COVID-19 Visualisation App

App 04 : ggplot2 Visualisation App

App 05 : Data Science App

App 06 : Word Cloud Generator

App 07 : UFC Dashboard

COURSE FEEDBACK

Thank you for attending this session. Please provide us with some feedback by clicking on the link below :


Feedback Link : https://form.gov.sg/640693fe6a72eb001243a03d

or you could scan the QR code provided below.

Thank you !