knitr::opts_chunk$set(comment=NA, fig.width=6, fig.height=6, echo = FALSE, eval = FALSE, message = FALSE, warning = FALSE, fig.align = 'center', out.width = "100%")
knitr::include_graphics("https://d21ii91i3y6o6h.cloudfront.net/gallery_images/from_proof/9306/small/1447177198/rstudio-hex-shiny-dot-psd.png")
Here are the introduction slides for this practical on Plotting 2.0: Shiny!
In this practical you'll practice creating interactive graphics with shiny
.
knitr::include_graphics("images/shiny_cheatsheet_ss.png")
If you don't have it already, you can access the shiny
cheatsheet here ttp://shiny.rstudio.com/images/shiny-cheatsheet.pdf
knitr::include_graphics("images/newapp_a_ss.png")
knitr::include_graphics("images/newapp_b_ss.png")
geyser.app
should now be open. Click the "Run App" button to open the app.knitr::include_graphics("images/newapp_d_ss.png")
knitr::include_graphics("images/newapp_e_ss.png")
By the end of this practical, you'll try to create the following app:
Start by following the example above so you have your own geyser.app
Explore the code in the app to see how it works. Where in the app is the user interface defined? Where is the server code? Where does the server code get access to the vector of geyser data? In what object is the geyser data stored?
Change the main title of the app from "Old Faithful Geyser Data" to "___'s first Shiny App!" using your first name.
In the server code, change the color of the bins of the histogram to "red"
. Reload your app to see your changes!
selectInput
to change bin colorsknitr::include_graphics("images/shinygeyser_ss_B2.png")
selectInput
like in the code below. # Add a new selectInput to your app below the sliderInput(): sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30), # <- Dont forget to put a comma here # HERE!!! Add Bin Color Select Input selectInput(inputId = "bincolor", label = "Color", choices = c("red", "blue", "green", "black"), selected = "black")
knitr::include_graphics("images/shinygeyser_ss_A.png")
hist()
) to use the new color input! In the server portion of the app, tell the histogram to use the new color input as follows:# Make this change to the hist() function in your app # This will tell Shiny that the colors of the histogram # bins should change based on the user's input hist(x, breaks = bins, col = input$bincolor, # HERE!!! Change color based on input$bincolor border = 'white')
knitr::include_graphics("images/shinygeyser_ss_B.png")
choices = c("red", "blue", "green", and "black")
. But R has so many more colors, what if we wanted the select input to show all of the named colors in R like "gold"
, "skyblue"
, and more obscure colors like "peachpuff4"
, "olivedrab"
and "lavender"
? It would be quite a pain to have to type all possible color names. Thankfully, we can easily pass a vector of color names to the choices
input. The function colors()
will return a vector of all 657 color names. In your console, try running colors()
to see all of the colors.# Print a vector of all color names colors()
choices = colors()
as follows:# This code will tell Shiny to include ALL 657 colors # in R as possible choices for the user in the bincolor input selectInput(inputId = "bincolor", label = "Color", choices = colors(), # <- HERE!!! change the choices to colors() selected = "black")
knitr::include_graphics("images/shinygeyser_ss_C.png")
checkboxInput
to add mean lineknitr::include_graphics("images/shinygeyser_ss_D.png")
"addmean"
# Add a new checkboxInput to your app checkboxInput(inputId = "addmean", label = "Add mean line?", value = FALSE)
hist()
code that creates the histogram, include the following:# Add this code just below the histogram code to add # a line at the mean IF the addmean checkbox is checked. if(input$addmean) { # If the addmean box is checked... # Add a vertical line at the mean of x abline(v = mean(x), lwd = 2, # Thickness lty = 2) # Dashed line } # close if statement
textInput
knitr::include_graphics("images/shinygeyser_ss_E.png")
textInput()
function in the user interface.# Add 2 text inputs to the sidepanel with textinput() textInput(inputId = "main", label = "Plot Title"), textInput(inputId = "xlab", label = "X-axis label")
hist()
function in the server code:hist(x, breaks = bins, col = input$bincolor, border = 'white', main = input$main, # HERE!!! Change main title based on input$main xlab = input$xlab) # HERE!!! Change x label based on input$xlab
tabsetPanel
tabsetPanel()
within the mainPanel()
function like this:# Create different tabs within your app by using tabsetPanel() # Here, we'll create three tabs, where the first tab mainPanel( tabsetPanel(type = "tabs", tabPanel("Histogram", plotOutput("distPlot")), # The original Histogram tabPanel("Summary"), # Empty for now tabPanel("Description") # Empty for now ) )
knitr::include_graphics("images/shinygeyser_ss_F.png")
renderPrint()
, and then assign the result to output$summary
. To do this, add the following code within your server function (you can actually put it anywhere in the server function!)# Add this code to the server function to return summary statistics output$summary <- renderPrint({ x <- faithful[, 2] # Define x again summary(x) })
"Summary"
tab panel to display this information. To do this, add the function verbatimTextOutput("summary")
to the "Summary"
tab panel as follows:# Add verbatimTextOutput("summary") to the Summary tab panel tabsetPanel(type = "tabs", tabPanel("Histogram", plotOutput("distPlot")), tabPanel("Summary", verbatimTextOutput("summary")), # <- HERE!!! tabPanel("Description") )
knitr::include_graphics("images/shinygeyser_ss_G.png")
h3(), p(), a()
functions. If you're familiar with HTML, these functions simply return HTML. Using the following code template, update the contents of the "Description"
tab panel to display some text and a link.# Add HTML functions to the Description tab tabsetPanel(type = "tabs", tabPanel("Histogram", plotOutput("distPlot")), tabPanel("Summary", verbatimTextOutput("summary")), tabPanel("Description", h3("Shiny is Awesome!"), p("You can really do anything with Shiny!"), a("Click me to go to the Shiny page", href = "https://shiny.rstudio.com/gallery/") ) )
knitr::include_graphics("images/shinygeyser_ss_H.png")
reactive()
knitr::include_graphics("images/shinygeyser_ss_I.png")
# Add a new select input called mydata selectInput(inputId = "mydata", label = "Dataset", choices = c("geyser", "diamonds", "economics"), selected = "geyser")
Now, in your server section, we need to define x
as a reactive value that depends on the user's input to input$mydata
. To do this, we'll remove the existing code that defines the object x
and replace it with x_reactive()
using the reactive()
function. The reactive()
function tells Shiny that x_reactive
is isn't a stable value, but will change depending on user input.
Step 1: Delete all existing code that defines the object x
(right now you'll find it in both the hist()
function and when we defined output$summary
x_reactive
as a reactive value that can change depending on the input$mydata
. If you haven't seen it before, the switch()
function is a very helpful function that works like a series of if-then statements.# x is a reactive value that depends on input$mydata # This code should replace the previous code that defined x # Put this code just after the server() function and BEFORE output$distPlot x_reactive <- reactive({ switch(input$mydata, # Look at the value of input$mydata... "geyser" = faithful[,2], # If the value is 'geyser', return data from faithful "economics" = economics$unemploy, # if the value is 'economics' return unemployment data "diamonds" = diamonds$price) # If the value is 'diamonds' return price data })
x
we need to replace x
with x_reactive()
(Don't forget the parentheses!!). Make this replacement for hist()
, summary()
, and abline()
. Here is how you can do it:# Change the value x to x_reactive() in seq(), hist(), abline() and summary() bins <- seq(min(x_reactive()), # HERE!!! Change to x_reactive() max(x_reactive()), # HERE!!! Change to x_reactive() length.out = input$bins + 1) # [Skip some code...] hist(x_reactive(), # HERE!!! Change to x_reactive() breaks = 10, col = input$bincolor, border = 'white', main = input$main, xlab = input$xlab) # [Skip some code...] abline(v = mean(x_reactive()), # HERE!!! Change to x_reactive() lwd = 2, lty = 2) # [Skip some code...] output$summary <- renderPrint({ summary(x_reactive()) # HERE!!! Change to x_reactive() })
C1. Now that you have multiple datasets, try removing the Plot title and X-axis label inputs (input$main
, input$xlab
), and instead have the plot automatically adjust the plot title and axis label based on the dataset the users selects. Just like we did with x_reactive()
, you'll need to assign the main title and x label as reactive values.
C2. Instead of a histogram, try creating a scatterplot as the main plotting output. Keep in mind that you'll now need to create two reactive values: x_reactive()
for the data on the x-axis and y_reactive()
for the y-axis. Then, as an optional argument (using a checkboxInput
), allow the user to add a regression line to the plot.
C3. Check out the RStudio Shiny Gallery at https://shiny.rstudio.com/gallery/ and look for a Shiny app you really like. Find the code, copy it, and paste it into a new app in RStudio. See if you can get the app to run. Then, customise it!
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.