Lab 6 is due on Friday, March 13th at noon. This can be hosted on the free shiny.io server (and linked here) OR imbedded in a Rmarkdown document.
library(ggplot2) # load ggplot2 library
library(shiny) # load shiny library
## Warning: package 'shiny' was built under R version 3.6.3
library(rsconnect) # load rsconnect library
## Warning: package 'rsconnect' was built under R version 3.6.3
##
## Attaching package: 'rsconnect'
## The following object is masked from 'package:shiny':
##
## serverInfo
theme_set(theme_bw(base_size=12)) # set the default plot theme for the ggplot2 library
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.
The tutorial at Rstudio is good but lengthy. I have tried to distill some of the principles below; if you like it and want more then I highly recommend the tutorial located here: https://shiny.rstudio.com/tutorial/
Note: install rsconnect via: devtools::install_github(‘rstudio/rsconnect’)
A ShinyApp consists of two R scripts:
These two scripts must be saved together in a single directory. Each app much be saved in a different directory.
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)
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
Example of a server script to accompany the ui script above:
library(shiny)
library(ggplot2)
# 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({
# set up the plot
pl <- ggplot(data = iris,
#Use aes_string below so that input$trait is interpreted
#correctly. The other variables need to be quoted
aes_string(x="Species",
y=input$trait,
fill="Species"
)
)
# draw the boxplot for the specified trait
pl + geom_boxplot()
})
})
The key elements of the above script:
shinyServer creates the server application.
renderPlot 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. In the ui.R script, we can access the plot as “boxPlot”
Pay attention to the modifications in how variables are given in the aes_string() argument to ggplot. This is different then what you have seen before with aes but enables direct access to input$trait from ggplot possible.
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
To try the app on your computer, save the above scripts in ui.R and server.R, respectively, in a directory for this app. Then from the R console:
library(shiny)
runApp(‘PATH_TO_APP_DIRECTORY’)
Now that we have our application, how do we share it?
Multiple options:
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.
If you have it on GitHub and the person you want to share it with has R they can use:
library(shiny)
runGitHub(repo = “Demo”,username = “yourusername”, subdir = “dirname”)
Go to the shiny io website and register for an account. You can use your github (you can obtain a free account) or google ID.
After registering go to account > tokens. Click on “show” and then “copy to clipboard” Paste it into R. After editing, the line should look something like: rsconnect::setAccountInfo(name=‘yourusername’, 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’)
Perform the following using the Iris dataset: Change the scripts above so that a violin plot is produced instead of a boxplot.
library(rsconnect)
library(shiny)
shinyUI<-fluidPage(
titlePanel("Violin Plot for Iris Data"),
helpText("This application creates a violin plot to show difference between",
"iris species. Please use the radio box below to choose a trait",
"for plotting"),
sidebarLayout(
sidebarPanel(
radioButtons("trait",
"Choose a trait to display:",
c("Sepal.Length",
"Sepal.Width",
"Petal.Length",
"Petal.Width")
)),
mainPanel(plotOutput(outputId = "violin_plot")
)
)
)
library(shiny)
library(ggplot2)
shinyServer<-function(input, output) {
output$violin_plot<-renderPlot({
ggplot(data = iris,
aes_string(x="Species",
y=input$trait,
fill="Species"
)
) + geom_violin()
})
}
shinyApp(ui=shinyUI,server=shinyServer)
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).
library(reshape2)
library(shiny)
shinyUI2<-fluidPage(
titlePanel("Box Plot for Iris Data by Species"),
helpText("This application creates a box plot to show difference between",
"iris traits. Please use the radio box below to choose a species",
"for plotting"),
sidebarLayout(
sidebarPanel(
radioButtons("Species", "Choose a species to display:", c("setosa", "versicolor", "virginica"))), mainPanel(plotOutput(outputId = "boxPlot"))))
library(shiny)
library(ggplot2)
shinyServer2<-function(input, output){
output$boxPlot<-renderPlot({
dat.m <- reshape2::melt(iris, iris.vars=c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width'))
dat.m2<-dplyr::filter(dat.m, Species==input$Species)
ggplot(data = dat.m2,
aes_string(x="variable", y="value", fill="variable"))+geom_boxplot()
})
}
shinyApp(ui=shinyUI2,server=shinyServer2)
Utilizing a dataset of your choice, design your own application
library(shiny)
shinyUI3<-fluidPage(
titlePanel("Violin Plot for Ozone Data"),
helpText("This application creates a violin plot to show differences between",
"the wind, temperature, and solar radiation of areas with different ozone coverage. Please use the radio box below to choose a trait",
"for plotting"),
sidebarLayout(
sidebarPanel(
radioButtons("Conditions",
"Choose a trait to display:",
c("Wind",
"Temp",
"Solar.R")
)),
mainPanel(plotOutput(outputId = "violin_plot3")
)
)
)
library(shiny)
library(ggplot2)
shinyServer3<-function(input, output) {
output$violin_plot3<-renderPlot({
ggplot(data = airquality,
aes_string(x="Ozone",
y=input$Conditions,
fill="Ozone"
)
) + geom_violin()
})
}
shinyApp(ui=shinyUI3,server=shinyServer3)