R Shiny

Reference

The basic parts of a Shiny app

How to build a Shiny app

Gallery

How to launch a Shiny app

24 beautifully-designed web dashboards that data geeks will love


Introduction

Let’s walk through the steps of building a simple Shiny application. A Shiny application is simply a directory containing an R script called app.R which is made up of a user interface object and a server function. This folder can also contain any any additional data, scripts, or other resources required to support the application.

ui

fluidPage: If you are creating a shiny application, the best way to ensure that the application interface runs smoothly on different devices with different screen resolutions is to create it using fluid page. This ensures that the page is laid out dynamically based on the resolution of each device.

The user interface can be broadly divided into three categories:

  • Title Panel: The content in the title panel is displayed as metadata, as in top left corner of above image which generally provides name of the application and some other relevant information.
  • Sidebar Layout: Sidebar layout takes input from the user in various forms like text input, checkbox input, radio button input, drop down input, etc. It is represented in dark background in left section of the above image.
  • Main Panel: It is part of screen where the output(s) generated as a result of performing a set of operations on input(s) at the server.R is / are displayed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#UI.R
#loading shiny library
library(shiny)

shinyUI(fluidPage(

#fluid page for dynamically adapting to screens of different resolutions.
titlePanel("Iris Dataset"),
sidebarLayout(
sidebarPanel(
#implementing radio buttons
radioButtons("p", "Select column of iris dataset:",
list("Sepal.Length"='a', "Sepal.Width"='b', "Petal.Length"='c', "Petal.Width"='d')),

#slider input for bins of histogram
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)

# Show a plot of the generated distribution
),
mainPanel(
plotOutput("distPlot")
)
)
))

server

This acts as the brain of web application. The server.R is written in the form of a function which maps input(s) to the output(s) by some set of logical operations. The inputs taken in ui.R file are accessed using $ operator (input$InputName). The outputs are also referred using the $ operator (output$OutputName). We will be discussing a few examples of server.R in the coming sections of the article for better understanding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#SERVER.R
library(shiny)

#writing server function
shinyServer(function(input, output) {

#referring output distPlot in ui.r as output$distPlot
output$distPlot <- renderPlot({

#referring input p in ui.r as input$p
if(input$p=='a'){
i<-1
}

if(input$p=='b'){
i<-2
}

if(input$p=='c'){
i<-3
}

if(input$p=='d'){
i<-4
}

x <- iris[, i]

#referring input bins in ui.r as input$bins
bins <- seq(min(x), max(x), length.out = input$bins + 1)

#producing histogram as output
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
})

Advantages and Disadvantages of Shiny

There are plenty of other data visualization tools out there. So, to help you compare what differentiates Shiny and what you can and cannot do with Shiny, let’s look at the advantages and disadvantages of using shiny.

Advantages :

  • Efficient Response Time: The response time of shiny app is very small, making it possible to deliver real time output(s) for the given input.
  • Complete Automation of the app: A shiny app can be automated to perform a set of operations to produce the desire output based on input.
  • Knowledge of HTML, CSS or JavaScript not required: It requires absolutely no prior knowledge of HTML, CSS or JavaScript to create a fully functional shiny app.
  • Advance Analytics: Shiny app is very powerful and can be used to visualize even the most complex of data like 3D plots, maps, etc.
  • Cost effective: The paid versions of shinyapps.io and shiny servers provide a cost effective scalable solution for deployment of shiny apps online.
  • Open Source: Building and getting a shiny app online is free of cost, if you wish to deploy your app on the free version of shinyapps.io

Disadvantages :

  • Requires timely updates: As the functions used in the app gets outdated sometimes with newer package versions, it becomes necessary to update your shiny app time to time.
  • No selective access and permissions: There’s no provision for blocking someone’s access to your app or proving selective access. Once the app is live on the web, it is freely accessible by everyone
  • Restriction on traffic in free version: In free version of shinyapps.io, you only get 25 active hours of your app per month per account.

Basic ui & server

1
2
3
4
5
6
7
8
9
10
11
12
# Basic UI
ui <- fluidPage( # Define UI for app ----
titlePanel(), # App title ---- at the top left corner
sidebarLayout( # Sidebar layout with input and output definitions ----
sidebarPanel( # Sidebar panel for inputs ----
sliderInput() # Input: Range & Default Value ----
),
mainPanel( # Main panel for displaying outputs ----
plotOutput() # Output: Chart Type ----
)
)
)
1
2
3
4
5
# Basic Server
# Define server logic required to draw a histogram ----
server <- function(input, output) { # Define server logic required to draw a histogram ----
output$ <- renderPlot({})
}
1
2
# Shiny App
shinyApp(ui = ui, server = server)

UI & Server

To get started building the application, create a new empty directory wherever you’d like, then create an empty app.R file within it. For purposes of illustration we’ll assume you’ve chosen to create the application at ~/shinyapp:

1
2
~/shinyapp
|-- app.R

Now we’ll add the minimal code required in the source file called app.R.

First, we load the shiny package:

1
library(shiny)

ui

Then, we define the user interface by calling the function pageWithSidebar:

1
2
3
4
5
6
7
8
9
10
11
12
# Define UI for miles per gallon app ----
ui <- pageWithSidebar(

# App title ----
headerPanel("Miles Per Gallon"),

# Sidebar panel for inputs ----
sidebarPanel(),

# Main panel for displaying outputs ----
mainPanel()
)

The three functions headerPanel, sidebarPanel, and mainPanel define the various regions of the user-interface. The application will be called “Miles Per Gallon” so we specify that as the title when we create the header panel. The other panels are empty for now.

Now let’s define a skeletal server implementation. To do this we call shinyServer and pass it a function that accepts two parameters, input and output:

server

1
2
3
4
# Define server logic to plot various variables against mpg ----
server <- function(input, output) {

}

Our server function is empty for now but later we’ll use it to define the relationship between our inputs and outputs.

app.R

Finally, we need the shinyApp function that uses the ui object and the server function we defined to build a Shiny app object.

Putting it altogether, our app.R script looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
library(shiny)

# Define UI for miles per gallon app ----
ui <- pageWithSidebar(

# App title ----
headerPanel("Miles Per Gallon"),

# Sidebar panel for inputs ----
sidebarPanel(),

# Main panel for displaying outputs ----
mainPanel()
)

# Define server logic to plot various variables against mpg ----
server <- function(input, output) {

}

shinyApp(ui, server)

We’ve now created the most minimal possible Shiny application. You can run the application by calling the runApp function as follows

1
2
> library(shiny)
> runApp("~/shinyapp")

Alternatively, if you are working on you can click the Run App button on your RStudio Editor.

If everything is working correctly you’ll see the application appear in your browser looking something like this:

We now have a running Shiny application however it doesn’t do much yet. In the next section we’ll complete the application by specifying the user interface object and implementing the server function

Inputs & Outputs

Adding Inputs to the Sidebar

The application we’ll be building uses the mtcars data from the R datasets package, and allows users to see a box-plot that explores the relationship between miles-per-gallon (MPG) and three other variables (Cylinders, Transmission, and Gears).

We want to provide a way to select which variable to plot MPG against as well as provide an option to include or exclude outliers from the plot. To do this we’ll add two elements to the sidebar, a selectInput to specify the variable and a checkboxInput to control display of outliers. Our user-interface definition looks like this after adding these elements:

ui

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Define UI for miles per gallon app ----
ui <- pageWithSidebar(

# App title ----
headerPanel("Miles Per Gallon"),

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Selector for variable to plot against mpg ----
selectInput("variable", "Variable:",
c("Cylinders" = "cyl",
"Transmission" = "am",
"Gears" = "gear")),

# Input: Checkbox for whether outliers should be included ----
checkboxInput("outliers", "Show outliers", TRUE)

),

# Main panel for displaying outputs ----
mainPanel()
)

If you run the application again after making these changes you’ll see the two user-inputs we defined displayed within the sidebar:

Creating the server function

Next we need to define the server-side of the application which will accept inputs and compute outputs. Our server function is shown below, and illustrates some important concepts:

  • Accessing input using slots on the input object and generating output by assigning to slots on the output object.
  • Initializing data at startup that can be accessed throughout the lifetime of the application.
  • Using a reactive expression to compute a value shared by more than one output.

The basic task of a Shiny server function is to define the relationship between inputs and outputs. Our function does this by accessing inputs to perform computations and by assigning reactive expressions to output slots.

Here is the source code for the full server function (the inline comments explain the implementation techniques in more detail):

server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Data pre-processing ----
# Tweak the "am" variable to have nicer factor labels -- since this
# doesn't rely on any user inputs, we can do this once at startup
# and then use the value throughout the lifetime of the app
mpgData <- mtcars
mpgData$am <- factor(mpgData$am, labels = c("Automatic", "Manual"))

# Define server logic to plot various variables against mpg ----
server <- function(input, output) {

# Compute the formula text ----
# This is in a reactive expression since it is shared by the
# output$caption and output$mpgPlot functions
formulaText <- reactive({
paste("mpg ~", input$variable)
})

# Return the formula text for printing as a caption ----
output$caption <- renderText({
formulaText()
})

# Generate a plot of the requested variable against mpg ----
# and only exclude outliers if requested
output$mpgPlot <- renderPlot({
boxplot(as.formula(formulaText()),
data = mpgData,
outline = input$outliers,
col = "#75AADB", pch = 19)
})

}

The use of renderText and renderPlot to generate output (rather than just assigning values directly) is what makes the application reactive. These reactive wrappers return special expressions that are only re-executed when their dependencies change. This behavior is what enables Shiny to automatically update output whenever input changes.

Displaying Outputs

The server function assigned two output values: output$caption and output$mpgPlot. To update our user interface to display the output we need to add some elements to the main UI panel.

In the updated user-interface definition below you can see that we’ve added the caption as an h3 element and filled in its value using the textOutput function, and also rendered the plot by calling the plotOutput function:

ui

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Define UI for miles per gallon app ----
ui <- fluidPage(

# App title ----
titlePanel("Miles Per Gallon"),

# Sidebar layout with input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Selector for variable to plot against mpg ----
selectInput("variable", "Variable:",
c("Cylinders" = "cyl",
"Transmission" = "am",
"Gears" = "gear")),

# Input: Checkbox for whether outliers should be included ----
checkboxInput("outliers", "Show outliers", TRUE)

),

# Main panel for displaying outputs ----
mainPanel(

# Output: Formatted text for caption ----
h3(textOutput("caption")),

# Output: Plot of the requested variable against mpg ----
plotOutput("mpgPlot")

)
)
)

Running the application now shows it in its final form including inputs and dynamically updating outputs:

Details

The shinyApp() function returns an object of class shiny.appobj. When this is returned to the console, it is printed using the print.shiny.appobj() function, which launches a Shiny app from that object.

You can also use a similar technique to create and run files that aren’t named app.R and don’t reside in their own directory. If, for example, you create a file called test.R and have it call shinyApp() at the end, you could then run it from the console with:

1
print(source("test.R"))

When the file is sourced, it returns a shiny.appobj — but by default, the return value from source() isn’t printed. Wrapping it in print() causes Shiny to launch it.

This method is handy for quick experiments, but it lacks some advantages that you get from having an app.R in its own directory. When you do runApp("newdir"), Shiny will monitor the file for changes and reload the app if you reload your browser, which is useful for development. This doesn’t happen when you simply source the file. Also, Shiny Server and shinyapps.io expect an app to be in its own directory. So if you want to deploy your app, it should go in its own directory.

Now that we’ve got a simple application running we’ll probably want to make some changes. The next article covers the basic cycle of editing, running, and debugging Shiny applications.

app.R

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Define UI for miles per gallon app ----
ui <- fluidPage(

# App title ----
titlePanel("Miles Per Gallon"),

# Sidebar layout with input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Selector for variable to plot against mpg ----
selectInput("variable", "Variable:",
c("Cylinders" = "cyl",
"Transmission" = "am",
"Gears" = "gear")),

# Input: Checkbox for whether outliers should be included ----
checkboxInput("outliers", "Show outliers", TRUE)

),

# Main panel for displaying outputs ----
mainPanel(

# Output: Formatted text for caption ----
h3(textOutput("caption")),

# Output: Plot of the requested variable against mpg ----
plotOutput("mpgPlot")

)
)
)

# Data pre-processing ----
# Tweak the "am" variable to have nicer factor labels -- since this
# doesn't rely on any user inputs, we can do this once at startup
# and then use the value throughout the lifetime of the app
mpgData <- mtcars
mpgData$am <- factor(mpgData$am, labels = c("Automatic", "Manual"))

# Define server logic to plot various variables against mpg ----
server <- function(input, output) {

# Compute the formula text ----
# This is in a reactive expression since it is shared by the
# output$caption and output$mpgPlot functions
formulaText <- reactive({
paste("mpg ~", input$variable)
})

# Return the formula text for printing as a caption ----
output$caption <- renderText({
formulaText()
})

# Generate a plot of the requested variable against mpg ----
# and only exclude outliers if requested
output$mpgPlot <- renderPlot({
boxplot(as.formula(formulaText()),
data = mpgData,
outline = input$outliers,
col = "#75AADB", pch = 19)
})

}

shinyApp(ui, server)

Example

The basic parts of a Shiny app

The Shiny package comes with eleven built-in examples that demonstrate how Shiny works. This article reviews the first three examples, which demonstrate the basic structure of a Shiny app.

Example 1: Hello Shiny

The Hello Shiny example is a simple application that plots R’s built-in faithful dataset with a configurable number of bins. To run the example, type:

1
2
library(shiny)
runExample("01_hello")

Shiny applications have ==two components==, a user interface object and a server function, that are passed as arguments to the shinyApp function that creates a Shiny app object from this UI/server pair. The source code for both of these components is listed below.

In subsequent sections of the article we’ll break down Shiny code in detail and explain the use of “reactive” expressions for generating output. For now, though, just try playing with the sample application and reviewing the source code to get an initial feel for things. Be sure to read the comments carefully.

The user interface is defined as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Define UI for app that draws a histogram ----
ui <- fluidPage(

# App title ---- at the top left corner
titlePanel("Hello Shiny!"),

# Sidebar layout with input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Slider for the number of bins ---- value means default value
sliderInput(inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30)

),

# Main panel for displaying outputs ----
mainPanel(

# Output: Histogram ----
plotOutput(outputId = "distPlot")

)
)
)

The server-side of the application is shown below. At one level, it’s very simple – a random distribution is plotted as a histogram with the requested number of bins. However, you’ll also notice that the code that generates the plot is wrapped in a call to renderPlot. The comment above the function explains a bit about this, but if you find it confusing, don’t worry, we’ll cover this concept in much more detail soon.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Define server logic required to draw a histogram ----
server <- function(input, output) {

# Histogram of the Old Faithful Geyser Data ----
# with requested number of bins
# This expression that generates a histogram is wrapped in a call
# to renderPlot to indicate that:
#
# 1. It is "reactive" and therefore should be automatically
# re-executed when inputs (input$bins) change
# 2. Its output type is a plot
output$distPlot <- renderPlot({

x <- faithful$waiting
bins <- seq(min(x), max(x), length.out = input$bins + 1)

hist(x, breaks = bins, col = "#75AADB", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times")

})

}

Finally, we use the shinyApp function to create a Shiny app object from the UI/server pair that we defined above.

1
2
# Create Shiny app ----
shinyApp(ui = ui, server = server)

We save all of this code, the ui object, the server function, and the call to the shinyApp function, in an R script called app.R. This is the same basic structure for all Shiny applications.

The next example will show the use of more input controls, as well as the use of reactive functions to generate textual output.

Example 2: Shiny Text

The Shiny Text application demonstrates printing R objects directly, as well as displaying data frames using HTML tables. To run the example, type:

1
2
library(shiny)
runExample("02_text")

The first example had a single numeric input specified using a slider and a single plot output. This example has a bit more going on: two inputs and two types of textual output.

If you try changing the number of observations to another value, you’ll see a demonstration of one of the most important attributes of Shiny applications: inputs and outputs are connected together “live” and changes are propagated immediately (like a spreadsheet). In this case, rather than the entire page being reloaded, just the table view is updated when the number of observations change.

Here is the user interface object for the application. Notice in particular that the sidebarPanel and mainPanel functions are now called with two arguments (corresponding to the two inputs and two outputs displayed):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# Define UI for dataset viewer app ----
ui <- fluidPage(

# App title ----
titlePanel("Shiny Text"),

# Sidebar layout with a input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Selector for choosing dataset ----
selectInput(inputId = "dataset",
label = "Choose a dataset:",
choices = c("rock", "pressure", "cars")),

# Input: Numeric entry for number of obs to view ----
numericInput(inputId = "obs",
label = "Number of observations to view:",
value = 10)
),

# Main panel for displaying outputs ----
mainPanel(

# Output: Verbatim text for data summary ----
verbatimTextOutput("summary"),

# Output: HTML table with requested number of observations ----
tableOutput("view")

)
)
)

The server side of the application has also gotten a bit more complicated. Now we create:

  • A reactive expression to return the dataset corresponding to the user choice
  • Two other rendering expressions (renderPrint and renderTable) that return the output$summary and output$view values

These expressions work similarly to the renderPlot expression used in the first example: by declaring a rendering expression you tell Shiny that it should only be executed when its dependencies change. In this case that’s either one of the user input values (input$dataset or input$obs).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Define server logic to summarize and view selected dataset ----
server <- function(input, output) {

# Return the requested dataset ----
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})

# Generate a summary of the dataset ----
output$summary <- renderPrint({
dataset <- datasetInput()
summary(dataset)
})

# Show the first "n" observations ----
output$view <- renderTable({
head(datasetInput(), n = input$obs)
})

}

Example 3: Reactivity

The Reactivity application is very similar to Hello Text, but goes into much more detail about reactive programming concepts. To run the example, type:

1
2
library(shiny)
runExample("03_reactivity")

The previous examples have given you a good idea of what the code for Shiny applications looks like. We’ve explained a bit about reactivity, but mostly glossed over the details. In this section, we’ll explore these concepts more deeply. If you want to dive in and learn about the details, see the Understanding Reactivity section, starting with Reactivity Overview.

What is Reactivity?

The Shiny web framework is fundamentally about making it easy to wire up input values from a web page, making them easily available to you in R, and have the results of your R code be written as output values back out to the web page.

1
input values => R code => output values

Since Shiny web apps are interactive, the input values can change at any time, and the output values need to be updated immediately to reflect those changes.

Shiny comes with a reactive programming library that you will use to structure your application logic. By using this library, changing input values will naturally cause the right parts of your R code to be reexecuted, which will in turn cause any changed outputs to be updated.

Reactive Programming Basics

Reactive programming is a coding style that starts with reactive values–values that change in response to the user, or over time–and builds on top of them with reactive expressions–expressions that access reactive values and execute other reactive expressions.

What’s interesting about reactive expressions is that whenever they execute, they automatically keep track of what reactive values they read and what reactive expressions they invoked. If those “dependencies” become out of date, then they know that their own return value has also become out of date. Because of this dependency tracking, changing a reactive value will automatically instruct all reactive expressions that directly or indirectly depend on that value to re-execute.

The most common way you’ll encounter reactive values in Shiny is using the input object. The input object, which is passed to your shinyServer function, lets you access the web page’s user input fields using a list-like syntax. Code-wise, it looks like you’re grabbing a value from a list or data frame, but you’re actually reading a reactive value. No need to write code to monitor when inputs change–just write reactive expression that read the inputs they need, and let Shiny take care of knowing when to call them.

It’s simple to create reactive expression: just pass a normal expression into reactive. In this application, an example of that is the expression that returns an R data frame based on the selection the user made in the input form:

1
2
3
4
5
6
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})

To turn reactive values into outputs that can viewed on the web page, we assigned them to the output object (also passed to the shinyServer function). Here is an example of an assignment to an output that depends on both the datasetInput reactive expression we just defined, as well as input$obs:

1
2
3
output$view <- renderTable({
head(datasetInput(), n = input$obs)
})

This expression will be re-executed (and its output re-rendered in the browser) whenever either the datasetInput or input$obs value changes.

Back to the Code

Now that we’ve taken a deeper look at some of the core concepts, let’s revisit the source code for the Reactivity example and try to understand what’s going on in more depth. The user interface object has been updated to include a text-input field that defines a caption. Other than that it’s very similar to the previous example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Define UI for dataset viewer app ----
ui <- fluidPage(

# App title ----
titlePanel("Reactivity"),

# Sidebar layout with input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Text for providing a caption ----
# Note: Changes made to the caption in the textInput control
# are updated in the output area immediately as you type
textInput(inputId = "caption",
label = "Caption:",
value = "Data Summary"),

# Input: Selector for choosing dataset ----
selectInput(inputId = "dataset",
label = "Choose a dataset:",
choices = c("rock", "pressure", "cars")),

# Input: Numeric entry for number of obs to view ----
numericInput(inputId = "obs",
label = "Number of observations to view:",
value = 10)

),

# Main panel for displaying outputs ----
mainPanel(

# Output: Formatted text for caption ----
h3(textOutput("caption", container = span)),

# Output: Verbatim text for data summary ----
verbatimTextOutput("summary"),

# Output: HTML table with requested number of observations ----
tableOutput("view")

)
)
)

The server function declares the datasetInput reactive expression as well as three reactive output values. There are detailed comments for each definition that describe how it works within the reactive system:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# Define server logic to summarize and view selected dataset ----
server <- function(input, output) {

# Return the requested dataset ----
# By declaring datasetInput as a reactive expression we ensure
# that:
#
# 1. It is only called when the inputs it depends on changes
# 2. The computation and result are shared by all the callers,
# i.e. it only executes a single time
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"pressure" = pressure,
"cars" = cars)
})

# Create caption ----
# The output$caption is computed based on a reactive expression
# that returns input$caption. When the user changes the
# "caption" field:
#
# 1. This function is automatically called to recompute the output
# 2. New caption is pushed back to the browser for re-display
#
# Note that because the data-oriented reactive expressions
# below don't depend on input$caption, those expressions are
# NOT called when input$caption changes
output$caption <- renderText({
input$caption
})

# Generate a summary of the dataset ----
# The output$summary depends on the datasetInput reactive
# expression, so will be re-executed whenever datasetInput is
# invalidated, i.e. whenever the input$dataset changes
output$summary <- renderPrint({
dataset <- datasetInput()
summary(dataset)
})

# Show the first "n" observations ----
# The output$view depends on both the databaseInput reactive
# expression and input$obs, so it will be re-executed whenever
# input$dataset or input$obs is changed
output$view <- renderTable({
head(datasetInput(), n = input$obs)
})

}

We’ve reviewed a lot code and covered a lot of conceptual ground in the first three examples. The next article focuses on the mechanics of building a Shiny application from the ground up.

If you have questions about this article or would like to discuss ideas presented here, please post on RStudio Community. Our developers monitor these forums and answer questions periodically. See help for more help with all things Shiny.

Example 4: Drawing histograms for iris dataset in R using Shiny

Creating Interactive data visualization using Shiny App in R (with examples)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#UI.R
library(shiny)
shinyUI(fluidPage(
titlePanel("Iris Dataset"),
sidebarLayout(
sidebarPanel(
radioButtons("p", "Select column of iris dataset:",
list("Sepal.Length"='a', "Sepal.Width"='b', "Petal.Length"='c', "Petal.Width"='d')),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
mainPanel(
plotOutput("distPlot")
)
)
))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#SERVER.R
library(shiny)
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
if(input$p=='a'){
i<-1
}

if(input$p=='b'){
i<-2
}

if(input$p=='c'){
i<-3
}

if(input$p=='d'){
i<-4
}

x <- iris[, i]

bins <- seq(min(x), max(x), length.out = input$bins + 1)
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
})

Example 5: Drawing Scatterplots for iris dataset in R using Shiny

Creating Interactive data visualization using Shiny App in R (with examples)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#UI.R
library(shiny)
shinyUI(fluidPage(
titlePanel("Iris Dataset"),
sidebarLayout(
sidebarPanel(
radioButtons("x", "Select X-axis:",
list("Sepal.Length"='a', "Sepal.Width"='b', "Petal.Length"='c', "Petal.Width"='d')),
radioButtons("y", "Select Y-axis:",
list("Sepal.Length"='e', "Sepal.Width"='f', "Petal.Length"='g', "Petal.Width"='h'))
),
mainPanel(
plotOutput("distPlot")
)
)
))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#SERVER.R
library(shiny)
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
if(input$x=='a'){
i<-1
}

if(input$x=='b'){
i<-2
}

if(input$x=='c'){
i<-3
}

if(input$x=='d'){
i<-4
}

if(input$y=='e'){
j<-1
}

if(input$y=='f'){
j<-2
}

if(input$y=='g'){
j<-3
}

if(input$y=='h'){
j<-4
}

s <- iris[, i]
k <- iris[, j]
plot(s,k)
})
})

Example 6: Loan Prediction Practice problem

Creating Interactive data visualization using Shiny App in R (with examples)

To provide you hands on experience of creating shiny app, we will be using the Loan Prediction practice problem.

To brief you about the data set, the dataset we will be using is a Loan Prediction problem set in which Dream Housing Finance Company provides loans to customers based on their need. They want to automate the process of loan approval based on the personal details the customers provide like Gender, Marital Status, Education, Number of Dependents, Income, Loan Amount, Credit History and others.

  1. We will be creating an explanatory analysis of individual variables of the practice problem.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#UI.R
#loading shiny
library(shiny)

shinyUI(fluidPage(
titlePanel("Loan Prediction III"),
sidebarLayout(
sidebarPanel(
#input using radiobuttons
radioButtons("s", "Select X-axis:",
list("Loan_ID"='a', "Gender"='b', "Married"='c', "Dependents"='d',"Education"='e', "Self_Employed"='f', "ApplicantIncome"='g', "CoapplicantIncome"='h', "LoanAmount"='i', "Loan_Amount_Term"='j', "Credit_History"='k', "Property_Area"='l', "Loan_Status"='m'))
),

# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#SERVER.R
library(shiny)

#loading shiny
shinyServer(function(input, output) {

#writing server function
output$distPlot <- renderPlot({

#creating distPlot
if(input$s=='a') { i<-1 }
if(input$s=='b') { i<-2 }
if(input$s=='c') { i<-3 }
if(input$s=='d') { i<-4 }
if(input$s=='e') { i<-5 }
if(input$s=='f') { i<-6 }
if(input$s=='g') { i<-7 }
if(input$s=='h') { i<-8 }
if(input$s=='i') { i<-9 }
if(input$s=='j') { i<-10 }
if(input$s=='k') { i<-11 }
if(input$s=='l') { i<-12 }
if(input$s=='m') { i<-13 }

#reading training dataset
train<-read.csv("train_u6lujuX_CVtuZ9i.csv")
X <- train[, i]
plot(X)
})
})

  1. Explanatory analysis of multiple variables of Loan Prediction Practice problem.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#UI.R
library(shiny)

shinyUI(fluidPage(
#writing title
titlePanel("Loan Prediction III"),

sidebarLayout(
sidebarPanel(
#taking inputs using radiobuttons
radioButtons("s", "Select X-axis:",
list("Loan_ID"='a1', "Gender"='b1', "Married"='c1', "Dependents"='d1',"Education"='e1', "Self_Employed"='f1', "ApplicantIncome"='g1', "CoapplicantIncome"='h1', "LoanAmount"='i1', "Loan_Amount_Term"='j1', "Credit_History"='k1', "Property_Area"='l1', "Loan_Status"='m1')),
#taking input k using radiobuttons
radioButtons("k", "Select Y-axis:",
list("Loan_ID"='a2', "Gender"='b2', "Married"='c2', "Dependents"='d2',"Education"='e2', "Self_Employed"='f2', "ApplicantIncome"='g2', "CoapplicantIncome"='h2', "LoanAmount"='i2', "Loan_Amount_Term"='j2', "Credit_History"='k2', "Property_Area"='l2', "Loan_Status"='m2'))
),

#displaying the output plot
mainPanel(
plotOutput("distPlot")
)
)
))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#SERVER.R
library(shiny)

#writing Server function
shinyServer(function(input, output) {

output$distPlot <- renderPlot({
if(input$s=='a1') { i<-1 }
if(input$s=='b1') { i<-2 }
if(input$s=='c1') { i<-3 }
if(input$s=='d1') { i<-4 }
if(input$s=='e1') { i<-5 }
if(input$s=='f1') { i<-6 }
if(input$s=='g1') { i<-7 }
if(input$s=='h1') { i<-8 }
if(input$s=='i1') { i<-9 }
if(input$s=='j1') { i<-10 }
if(input$s=='k1') { i<-11 }
if(input$s=='l1') { i<-12 }
if(input$s=='m1') { i<-13 }
if(input$k=='a2') { j<-1 }
if(input$k=='b2') { j<-2 }
if(input$k=='c2') { j<-3 }
if(input$k=='d2') { j<-4 }
if(input$k=='e2') { j<-5 }
if(input$k=='f2') { j<-6 }
if(input$k=='g2') { j<-7 }
if(input$k=='h2') { j<-8 }
if(input$k=='i2') { j<-9 }
if(input$k=='j2') { j<-10 }
if(input$k=='k2') { j<-11 }
if(input$k=='l2') { j<-12 }
if(input$k=='m2') { j<-13 }

#read data
train<-read.csv("train_u6lujuX_CVtuZ9i.csv")
X <- train[, i]
Y <- train[, j]
plot(X,Y)
})
})


Advanced

Explore Shiny app with these add-on packages

Creating Interactive data visualization using Shiny App in R (with examples)

To add some more functionality to your Shiny App, there are some kick-ass packages available at your disposal. Here are few from RStudio.

  1. http://rstudio.github.io/shinythemes/
  2. http://rstudio.github.io/leaflet/
  3. https://rstudio.github.io/shinydashboard/
  4. http://shiny.rstudio.com/reference/shiny/latest/

Additional Resources

In the article I have covered the key areas of Shiny to help you get started with it. Personally to me Shiny is an interesting creation and to make the most of it, I think you should explore more. Here are few additional resources for you to become an adept in creating Shiny Apps.

  1. http://shiny.rstudio.com/tutorial/
  2. http://shiny.rstudio.com/images/shiny-cheatsheet.pdf
  3. http://shiny.rstudio.com/articles/
  4. http://www.showmeshiny.com/.
  5. http://www.shinyapps.io/
  6. http://shiny.rstudio.com/gallery/google-charts.html
  7. Shiny Google User Group

UI

sidebarPanel

A

actionButton

C

checkboxGroupInput

D

dateInput

dateRangeInput

F

fileInput

N

numericInput

P

passwordInput

R

radioButtons

S

selectInput

sliderInput

submitButton

T

textAreaInput

textInput

V

varSelectInput

Server

plotOutput