Make a web app with Shiny

Today we will learn how to make and deploy interactive web applications with Shiny. Shiny allows you to display your R analysis on the web to anyone. For example:

The tutorial at Rstudio is good but pretty involved. I have tried to distill some of the principles below; if you like it and want more then I highly recommend the tutorial.

Resources

The cheat sheet may be helpful.

Components of a Shiny App

A ShinyApp consists of two R scripts:

  • ui.R This script controls the user interface (i.e. the design of the webpage, the input and the output).
  • server.R This script does the work of performing any analysis, creating graphs, and creating tables

These two scripts must be saved together in a single directory. Each app much be saved in a different directory. (It is now possible to combine these into a single script but we will keep them separate for this class)

ui.R

Here is a sample ui.R script. This script makes use of R’s built in data set on iris. For more information on this data set you can type ?iris in R.

library(shiny)

# Define UI for application that draws a histogram
shinyUI(fluidPage( #create the overall page
  
  # Application title
  titlePanel("Iris Data"),
  
  # Some helpful information
  helpText("This application creates a boxplot to show difference between",
           "iris species.  Please use the radio box below to choose a trait",
           "for plotting"),
  
  # Sidebar with a radio box to input which trait will be plotted
  sidebarLayout(
    sidebarPanel(
      radioButtons("trait", #the input variable that the value will go into
                   "Choose a trait to display:",
                   c("Sepal.Length",
                     "Sepal.Width",
                     "Petal.Length",
                     "Petal.Width")
      )),
      
      # Show a plot of the generated distribution
      mainPanel(
        plotOutput("boxPlot")
      )
    )
  ))

There are several components in the above script (and note that they are nested)

  • shinyUI This is the overall function that creates that user interface
    • fluidPage This creates the layout for our webpage. The webpage has three components:
    • titlePanel Should be obvious
    • sidebarLayout Creates a sidebar layout within fluidpage
      • sidebarPanel specifies the sidebar panel.
        • radioButtons specifies that we want radio buttons in this sidebar panel. We could have additional input functions here.
      • mainPanel specifies that we want a main panel as well
      • plotOutput what we want on the main panel. We could have more than one of these, or could have tables, etc.

To see all the types of input and output that can be included, see the Shiny reference. Of particular interest:

  • tabPanel if we want multiple tabs on the page
  • checkboxInput
  • sliderInput
  • tableOutput
  • textOutput

server.R

Below is an example of a server script to accompany the ui script above

library(shiny)
library(tidyverse)

# Define server logic required to draw a boxplot
shinyServer(function(input, output) {
  
  # Expression that generates a boxplot. The expression is
  # wrapped in a call to renderPlot to indicate that:
  #
  #  1) It is "reactive" and therefore should re-execute automatically
  #     when inputs change
  #  2) Its output type is a plot
    
  output$boxPlot <- renderPlot({
    
    plotTrait <- as.name(input$trait) # convert string to name
    
    # set up the plot
    pl <- ggplot(data = iris,
                 aes(x=Species,
                            y= !! plotTrait, # !! to use the column names contained in plotTrait
                            fill=Species
                            )
    )
    
    # draw the boxplot for the specified trait
    pl + geom_boxplot()
  })
})

The key elements of the above script:

  • shinyServer this creates the server application.
    • renderPlot this tells R that the enclosed code will generate a plot that is to be put on the webpage. Note that there are similar functions for outputting tables and text.
  • Information is passed between the ui.R and server.R scripts via the input and output variables.
    • In the ui.R script we specified that the radioButton() information should be placed in “trait”. server.R accesses that through input$trait
    • Similarly in the server.R script we specify that the rendered plot goes into output$boxPlot. Then in ui.R we can access the plot as “boxPlot”
  • Pay attention to the modifications in how variable are given in the aes() argument to ggplot. Because we want aes() to use the contents of input$trait to select a column, we first have to convert input$trait to a name with as.name() (placing the contents in plotTrait) and then use !! to tell aes() to get the name out of plotTrait instead of just taking it literally as a column name.
  • Important any one-time data loading or manipulation (i.e. reading in a file) should be done BEFORE, not within, any renderNNN statements. You can put it just below the library statements, before the shinyServer

trying it

To try the app on your computer:

  1. Create a new directory for this app demoApp (you can use a different name)
  2. Save the above scripts in ui.R and server.R, respectively, inside the ‘demoApp` directory that you just created for this app.
  3. Then either press the “RunApp” button in Rstudio, or, from the R console:
library(shiny)
runApp('PATH_TO_APP_DIRECTORY')    

If your working directory is the App directory, you can leave out the path to the App directory. ie runApp() will run the App

Practice 1 (not graded)

Change the scripts above so that a violin plot is produced instead of a boxplot.

Practice 2 (not graded)

Change the scripts above so that all of the traits are plotted as a boxplot but only for a single species. (The x-axis should be trait; the user selects species).

Deployment

Once you have an awesome application how do you share it?

For this lab, we will use Rstudio’s free shiny server

To use their server (required to complete the assignment, but __wait to do these steps until you have your app working__)
  
* One person in your group needs to go to the [shiny io website](http://www.shinyapps.io/) and register for an account.  You can use your github or google ID.
* After registering go to account > tokens.  Click on "show", Click on "Show Secret", and then "copy to clipboard"
* Paste it into the R command below and run it.  It should look something like: 
rsconnect::setAccountInfo(name='jnmaloof', token='45515FE2BB923C41A95D9768C9AD6F91', secret='somelonggibberishheredonotshare')
* This only needs to be done once per computer
  
Once you have signed up for an account and authenticated it a simple as:
library(rsconnect)
deployApp('path/to/your/app')

The above process is also described in the Shinyio user guide if would like more details

You can see my version here

Assignment

Your team should work together to create and deploy a ShinyApp that plots some aspect of the data from the BLAST or RICE labs. The app should allow user input that modifies the plot in a useful way.

I have listed some ideas below, but feel free to choose something else

RICE data ideas

You might want to limit the user input to 5 or 10 traits in the examples below, just to save yourself some typing and to keep the radio button list not too long (or use selectize)

  • Interactive plot showing histograms or violin plots or boxplots of user-selected phenotypic data split by ancestral population assignment or region. You could also allow the user to choose whether it was a histogram or a violin plot, etc.
  • scatter plot of any two traits (user chosen), colored by the values of a third (user chosen).
  • If you want to get fancy in either of the above then you could use the selectize tool to allow the user to select from all of the possible phenotypes.

Other data ideas

  • Feel free to use any data set that you are interested in; if you work in an lab maybe a data set from your lab work.
  • You could use the tomato data set that was used in the ggplot tutorial and:
    • explore relationship between altitude and plant height
    • plot trait averages per species letting the user choose the trait
    • etc.

Download tomato data here

Scoring (out of 20 points)

16 points for a functional, interactive web app deployed on shinyapps.io and pushed to GitHub.

+ 2 points for using two or more input widget types (slider and radio buttons, for example).
+ 2 points for good annotation on the web page (a new user would understand what the app is about).
- 2 or more points for each student that does not make at least 2 substantive commits to the team repository.

Getting started with the assignment

  • One person in each team should click github link, create a team, and create a repo.
  • Other members of the team should then click on the github link and join that team.
  • Everyone should clone the repo.
  • Discuss your goals and what you want your final product to look like with your team members.
  • Start by having one person create an app using the RStudio template
    • click on the green “+” RStudio and select “Shiny Web App”.
    • select “multiple file”, give it a name, and have it save it in your repo.
    • you can then modify these files to make it your own.
  • Start simple.
  • Remember that you can use git commit and push and pull to share your file changes among the team. I recommend that you do not have two people work on the same section of the same file at once; it makes it hard to do automatic merge when you pull.
  • Once you get it running, sign up for an account and deploy it on shiny.io. See deployment, above.
  • Place a link to your shiny web app in the README.md in your github repository.
  • List the students that contributed in your README.md in your github repository.

Going further

To get further inspiration, checkout out the Shiny Gallery

You can also include Shiny apps directly in your Rmarkdown files to be rendered into html. In some ways the syntax is even easier because you only need a single file. You can also include interactive graphs in slide presentations this way.

Other ways to deploy (NOT NEEDED FOR BIS180L)

deployment

Now that we have our awesome application how do we share it?

Multiple options:

  1. If you are sharing it with someone that uses R and has the shiny library installed, then you can just send it to them, they can download it, and run it as above.
  2. If you have it on GitHub and the person you want to share it with has R they can use:

     library(shiny)
     runGitHub(repo = "HamiltonDemos",username = "jnmaloof", subdir = "BinomialDrift")
    
  3. You can use Rstudio’s free shiny server

    To use their server (required to complete the assignment)

    • Go to the shiny io website and register for an account. You can use your github or google ID.
    • After registering go to account > tokens. Click on “show” and then “copy to clipboard”
    • Paste it into R. It should look something like:
     rsconnect::setAccountInfo(name='jnmaloof', token='45515FE2BB923C41A95D9768C9AD6F91', secret='somelonggibberishheredonotshare')
    
    • This only needs to be done once per computer

    Once you have signed up for an account and authenticated it a simple as:

     library(rsconnect)
     deployApp('path/to/your/app')
    

    The above process is also described in the Shinyio user guide if would like more details

    You can see my version here

  4. If you are advanced you can run your own server (I actually set up a server my lab–it isn’t that hard)