Introduction to Shiny
Author: Alli N. Cramer
Shiny is an R package that allows you to create interactive data visualizations. Shiny can create HTML pages which can allow users to generate graphs, maps, etc. based on underlying data and predetermined functions.
If you use R Studio, Shiny comes pre-installed and can be accessed by clicking File -> New File -> Shiny Web App. If you use native R you will need to make sure you have the shiny package.
For cool examples of shiny, and for more help, see the shiny page, https://shiny.rstudio.com/.
Shiny File Format
When you open a new Shiny file, called a shiny "app", there are two possible ways to do it. One is as a single app script, the other is as two scripts, a ui.R and a server.R script, which work together to make a functioning app script.
In this example we will use a single app script. As will become apparent, the two-script version is suitable for more complicated shiny files, but relies on the same format as the basic app script.
Shiny Component Parts
The two essential parts of shiny are the ui and the server parts. When you open a brand new shiny app you will get a preformatted shiny app which includes these two parts. Format wise, the ui and the server look like, and function similarly to, functions in R. In the example page below the ui specifies the layout of the html page and where a user can add inputs (changing the number of bins in a histogram). The server specifies the data source for the histogram (the built in dataset faithful), the plot format itself (hist()), and where user input is incorporated (the input$bins call).
1#
2# This is a Shiny web application. You can run the application by clicking
3# the 'Run App' button above.
4#
5# Find out more about building applications with Shiny here:
6#
7# http://shiny.rstudio.com/
8#
9
10library(shiny)
11
12# Define UI for application that draws a histogram
13ui <- fluidPage(
14
15 # Application title
16 titlePanel("Old Faithful Geyser Data"),
17
18 # Sidebar with a slider input for number of bins
19 sidebarLayout(
20 sidebarPanel(
21 sliderInput("bins",
22 "Number of bins:",
23 min = 1,
24 max = 50,
25 value = 30)
26 ),
27
28 # Show a plot of the generated distribution
29 mainPanel(
30 plotOutput("distPlot")
31 )
32 )
33)
34
35# Define server logic required to draw a histogram
36server <- function(input, output) {
37
38 output$distPlot <- renderPlot({
39 # generate bins based on input$bins from ui.R
40 x <- faithful[, 2]
41 bins <- seq(min(x), max(x), length.out = input$bins + 1)
42
43 # draw the histogram with the specified number of bins
44 hist(x, breaks = bins, col = 'darkgray', border = 'white')
45 })
46}
47
48# Run the application
49shinyApp(ui = ui, server = server)
More Complicated Inputs
The base example above is effective but we can easily do more complicated apps. For example, what if we wanted to change the source data being plotted based on user inputs?
To do this we need to use what are called "reactives". We need to specify the user input in the ui, and then call it in the server function, but in a way that lets Shiny know that the input will require the dataset and graph to be re-run. We can do this two ways, by specifying the user input with a get() command (good for simple changes) or by explicitly telling the server the data is reactive.
In the example below we have plotted the built in iris dataset. In this example we use radio buttons to select the response variable in the ui. The data is then integrated into the plot using the get() command.
We alter what subset of the data is being plotted by creating a reactive dataset. In the ui we have chosen to select species data from a drop down menu, selectInput(), however the ui component could be radio buttons, or a slider, etc. The server component specifies the data is reactive before developing the plot:
1dat <- reactive({
2 df <- subset(iris, Species == input$species)
3 return(df)})
Here we have explicitly told the server that the dat object called in a later plot is a reactive object which changes based on the user input for Species. When we format data this way we need to be careful to call the dat object with open parentheses, "data = dat()" in this case, because the object is not static. See example below.
1library(shiny)
2
3# Define UI for application that draws a plot with a linear model
4ui <- fluidPage(
5
6 # Application title
7 titlePanel("Iris Data Plot"),
8
9 # Sidebar with a slider input for number of bins
10 sidebarLayout(
11 sidebarPanel(
12 selectInput("species",
13 "which species",
14 choices = c("setosa", "versicolor", "virginica")
15 )
16 ),
17 radioButtons("var",
18 "response variable",
19 c("Sepal Width" = "Sepal.Width",
20 "Petal Length" = "Petal.Length",
21 "Petal Width" = "Petal.Width"))
22 ),
23
24 # Show a plot of the generated distribution
25 mainPanel(
26 plotOutput("modplot")
27 )
28 )
29
30# Define server logic required to draw a plot
31server <- function(input, output) {
32 dat <- reactive({
33 df <- subset(iris, Species == input$species)
34 return(df)})
35
36 output$speciesname <- renderText(get(input$species))
37
38 output$modplot <- renderPlot({
39 # generate models based on input$variable from ui.R
40
41 mod <- lm(get(input$var) ~ Sepal.Length, data = dat())
42
43 # plot based on selected variables and add model on top
44 plot(get(input$var) ~ Sepal.Length, data = dat())
45 abline(mod)
46 })
47}
48
49# Run the application
50shinyApp(ui = ui, server = server)