10 R Shiny
10.1 Introduction
Shiny (Chang et al. 2021) is a web application framework for R that enables to build interactive web applications.
The R shiny Cheatsheet can be found HERE
The Big Concept
Interact. Analyze. Communicate.
Take a fresh, interactive approach to telling your data story with Shiny. Let users interact with your data and your analysis. And do it all with R.
If you’ve never used Shiny before, welcome! Shiny is an R package that allows you to easily create rich, interactive web apps. Shiny allows you to take your work in R and share it through a web browser .
In the past, creating web apps was hard for most R users because:-
You need a deep knowledge of web technologies like HTML, CSS, JavaScript, server configuration.
How do Data Analysts and Scientists use R :-
To create dashboards that track important high-level performance indicators, while facilitating drill down into metrics that need more investigation.
To replace hundreds of pages of PDFs with interactive apps that allow the user to jump to the exact slice of the results that they care about.
To communicate complex models to a non-technical audience with informative visualisations and interactive sensitivity analysis.
To provide self-service data analysis for common workflows, replacing email requests with a Shiny app that allows people to upload their own data and perform standard analyses. You can make R analyses available to users with no programming skills. e.g. This App
In short, Shiny gives you the ability to pass on some of your R superpowers to anyone who can use the internet to access the web.
To create Shiny apps, there is no web development experience required, although greater flexibility and customization can be achieved by using HTML, CSS or JavaScript.
While there is a wealth of material available on the internet to help you get started with Shiny, it can be difficult to see how everything fits together. This guide will take a fairly predominantly live coding approach, rather than a lecture-only approach.
This section will teach you the basics of Shiny app programming, giving you skills that will form the basis of almost any app you want to build. By the end of the section, you will have created a custom shiny app.
10.1.1 Some sample of Live Shiny Apps
The following are some diverse examples of Shiny apps :-
Pearl Tap Into Twitter: This dashboard is part of the Pearl Data Firm Ecosystem, This dashboard can be used to monitor your twitter marketing campiagns.
R Shiny Whatsapp Chat Analyser Tool:This is an Interactive R shiny Application that enables upload of a your chat from whatsapp, and generates visualizations and descriptive statistics to help track, analyze, and to gain deeper insight in your chats.
Charcoal Equivalent Statistics: An application tool to estimate the equivalent grid power and number of trees that would replace a given percentage of heating functions done by charcoal.
HK Data Analyzer: An Interactive R shiny Application that enables upload of a data set based on HK Data template, and generates visualizations and descriptive statistics to help track, analyze and gain insights.
Shiny Enterprise Dashboard: A more advanced Shiny Application
And Many More
10.1.2 What experience do I need?
You need to have basic familiarity with R, including data import, data processing, visualization, and functions and control structures (e.g., if/else). Instruction will be done using RStudio.
Some familiarity with ggplot2
and dplyr
would be useful. You definitely do not need to be an expert coder, but the following code should not be challenging to understand.
If you want to brush up on your R , this self study guide provides a comprehensive overview.
In this section you will learn about :-
The basic principles to build a Shiny app.
How to build the user interface and server parts of a shiny app
How to create reactivity.
How to design a basic layout for the user interface
How to share with others you application.
Therefore, this section is designed to take you from knowing nothing about Shiny to being able to develop shiny apps to help you share your analysis in an interactive way.
However,More advanced topics such as customization of reactions and appearance of the app can be found in the Shiny tutorials website. Examples of more advanced Shiny apps can be seen in the Shiny gallery.
10.2 Structure Of a shiny App
10.2.1 Basic file structures
To understand shiny
, we first need to understand how the file structure of an app works!
Note:
You need to make a brand new directory before we start. This can actually be made easier by choosing New project in Rstudio, and choosing Shiny Web Application. This will create the basic structure of a shiny app for you.
When opening this project, you’ll notice there is a .R
file already present called app.R. It is essential that we have one of two basic file structures:
One file called app.R, or
Two files, one called ui.R and the other server.R
However, i personally prefer and recommend a two files structure.
The two files help you not to have a length code in one file, hence avoiding longer scrolling,
Also makes following up your code workflow especially if the code is extensive, AND
most of the Shiny apps I come accross seem to follow the convention of using differente files.
BUT, does is make any difference, technically?
10.3 Building the UI
Since you have creating your first basic shiny App, Let’s now explore the details that make your UI more have more functionality.
In this sub section , we are going to focus on the front end, and look at a number of the inputs and outputs provided by Shiny. These gives you the ability to capture many types of data and display many types of R output.
Not that there are very many shiny extensions for advanced added functionality that we may not look at here such as shinyWidgets, colorpicker, etc. There is a comprehensive, actively-maintained list of other packages extensions HERE.
10.3.1 Inputs
The following are standard Shiny input widgets (click the image below to view a live app demostration)
function | widget |
---|---|
actionButton |
Action Button |
checkboxGroupInput |
A group of check boxes |
checkboxInput |
A single check box |
dateInput |
A calendar to aid date selection |
dateRangeInput |
A pair of calendars for selecting a date range |
fileInput |
A file upload control wizard |
helpText |
Help text that can be added to an input form |
numericInput |
A field to enter numbers |
radioButtons |
A set of radio buttons |
selectInput |
A box with choices to select from |
sliderInput |
A slider bar |
submitButton |
A submit button |
textInput |
A field to enter text |
10.3.1.1 Adding an Input widget to the app
All input functions functions have the same format;-
-
inputId
. This is the unique identifier used to connect the UI with the SERVER. if your UI has an input with ID"amount"
, the server function will access it withinput$amount
.Note that the
inputId
must be a simple text that follow the rules of indentifies i.e.unique
contains only letters, numbers, and underscores (no spaces, dashes, periods, or other special characters allowed!).
label
. This is used to create a human-readable label for the control. Shiny doesn’t place any restrictions on this string, but you’ll need to carefully think about it to make sure that your app is usable by humans!-
value
, Enables you set the default value.Note that: The other remaining arguments are unique to each input function
Some Examples of Inputs
10.3.1.2 Inputting a text
Collect small amounts of text with textInput()
, passwords with passwordInput(), and paragraphs of text with textAreaInput()
.
fluidRow(textInput("username", "Enter user Name?"), passwordInput("password",
"Enter password?"), textAreaInput("describe", "In One Sentence,Describe yourself",
rows = 4))
10.3.1.3 Inputting numeric inputs
To collect numeric values, create a text box with numericInput()
or a slider with sliderInput()
.
fluidPage(numericInput("age", "What is your Age", value = 0,
min = 0, max = 120), sliderInput("rate", "Out of 10, How do you rate your R skills",
value = 5, min = 0, max = 10), sliderInput("score", "What was your Score in R test",
value = c(0, 50), min = 0, max = 100))
Sliders are extremely customization and there are many ways to tweak their appearance. See ?sliderInput
and https://shiny.rstudio.com/articles/sliders.html for more details.
10.3.1.4 Inputting Dates
Collect a single day with dateInput()
or a range of two days with dateRangeInput()
. These provide a convenient calendar picker, and additional arguments like datesdisabled
and daysofweekdisabled
allow you to restrict the set of valid inputs.
fluidRow(dateInput("dob", "Enter you date of birth?"), dateRangeInput("start_course",
"When do you expect to Practce R?"))
Date format, language, and the day on which the week starts defaults to US standards. If you are creating an app with an international audience, set format
, language
, and weekstart
so that the dates are natural to your users.
10.3.1.5 Inputting from choices
There are two different approaches to allow the user to choose from a prespecified set of options: selectInput()
and radioButtons()
.
selectInput(inputId = "language1", label = "Which Language are you most proficient?",
choices = c("R", "Python", "C", "C++", "SQL", "HTML", "JavaScript"))
radioButtons(inputId = "language2", label = "What other languages do you Know?",
choices = c("R", "Python", "C", "C++", "SQL", "HTML", "JavaScript"))
Radio buttons have two nice features: they show all possible options, making them suitable for short lists, and via the choiceNames
/choiceValues
arguments, they can display options other than plain text. choiceNames
determines what is shown to the user; choiceValues
determines what is returned in your server function.
radioButtons("status", "How are you?", choiceNames = list("angry",
"happy", "sad"), choiceValues = c(1, 2, 3))
If you have a very large set of possible options, you may want to use “server-side” selectInput()
so that the complete set of possible options are not embedded in the UI (which can make it slow to load), but instead sent as needed by the server. You can learn more about this advanced topic at https://shiny.rstudio.com/articles/selectize.html#server-side-selectize.
There’s no way to select multiple values with radio buttons, but there’s an alternative that’s conceptually similar: checkboxGroupInput()
.
checkboxGroupInput(inputId = "skills_known", label = h3("Select the packages you know"),
choices = list(shiny = 1, tidyverse = 2, rhino = 3, ggplot2 = 4,
lubridate = 5, htmltools = 6, others = 7), selected = 1)
10.3.1.6 File uploads
Allow the user to upload a file with fileInput()
fileInput(inputId = "data_upload", label = "Upload your data",
NULL)
fileInput()
requires special handling on the server side, and is discussed in detail latyer in th section.
10.3.2 Outputs
Outputs in the UI create placeholders that are later filled by the server function.
Shiny provides a family of functions that turn R objects into output for your user interface. Each function creates a specific type of output.
Output function | Creates |
---|---|
dataTableOutput |
DataTable |
htmlOutput |
raw HTML |
imageOutput |
image |
plotOutput |
plot |
tableOutput |
table |
textOutput |
text |
uiOutput |
raw HTML |
verbatimTextOutput |
text |
Like inputs, outputs take a unique ID as their first argument, if your UI specification creates an output with ID "plot"
, you’ll access it in the server function with output$plot
.
10.3.2.1 Text Output
Output regular text with textOutput()
and fixed code and console output with verbatimTextOutput()
.
10.3.2.2 Tables Output
There are two options for displaying data frames in tables:
tableOutput()
andrenderTable()
render a static table of data, showing all the data at once.dataTableOutput()
andrenderDataTable()
render a dynamic table, showing a fixed number of rows along with controls to change which rows are visible.
tableOutput()
is most useful for small, fixed summaries (e.g. model coefficients); dataTableOutput()
is most appropriate if you want to expose a complete data frame to the user.
10.3.2.3 Plot Output
You can display any type of R graphic with plotOutput()
and renderPlot()
:
10.3.2.4 Downloads
You can let the user download a file with downloadButton()
or downloadLink()
.
10.3.3 HTML content
The appearance of a Shiny app can be customized by using HTML content such as text and images. We can add HTML content with the shiny::tags
object. tags
is a list of functions that build specific HTML content. The names of the tag functions can be seen with names(tags)
. Some examples of tag functions, their HTML equivalents, and the output they create are the following:
h1()
:<h1>
first level header,h2()
:<h2>
second level header,strong()
:<strong>
bold text,em()
:<em>
italicized text,a()
:<a>
link to a webpage,img()
:<img>
image,br()
:<br>
line break,hr()
:<hr>
horizontal line,div
:<div>
division of text with a uniform style.
We can use any of these tag functions by subsetting the tags
list. For example, to create a first level header we can write tags$h1("Header 1")
, to create a link to a webpage we can write tags$a(href = "www.webpage.com", "Click here")
, and to create a section in an HTML document we can use tags$div()
.
Some of the tag functions have equivalent helper functions that make accessing them easier. For example, the h1()
function is a wrapper for tags$h1()
, a()
is equivalent to tags$a()
, and div()
is equivalent to tags$div()
. However, most of the tag functions do not have equivalent helpers because they share a name with a common R function.
We can also include an HTML code different from the one that is provided by the tag functions. To do that, we need to pass a character string of raw HTML code to the HTML()
function: tags$div(HTML("<strong> Raw HTML </strong>"))
. Additional information about tag functions can be found in Customize your UI with HTML and the Shiny HTML Tags Glossary.
10.3.4 Layouts
Shiny includes a number of facilities for laying out the components of an application. They include :
A
sidebarLayout()
: for placing asidebarPanel()
of inputs alongside amainPanel()
output content.Custom layouts using Shiny’s grid layout system (i.e.,
fluidRow()
&column()
).Segmenting layouts using the
tabsetPanel()
andnavlistPanel()
functions.Creating applications with multiple top-level components using the
navbarPage()
function.
The outlook can be customized manually or by applying application themes, check out the application themes article here .
10.3.4.1 Sidbar Layout
This layout provides a sidebar for inputs and a large main area for output:
fluidPage(titlePanel("Side bar Layout!"), sidebarLayout(sidebarPanel(),
mainPanel()))
Grid Layout
The familiar sidebarLayout()
described above makes use of Shiny’s lower-level grid layout functions. Rows are created by the fluidRow()
function and include columns defined by the column()
function. Column widths are based on the Bootstrap 12-wide grid system, so should add up to 12 within a fluidRow()
container.
To illustrate, here’s the sidebar layout implemented using the fluidRow()
, column()
and wellPanel()
functions:
fluidPage(titlePanel("Crid Layout"), fluidRow(column(4, wellPanel(sliderInput())),
column(8, )))
10.3.4.2 Tabsets
Often applications need to subdivide their user-interface into discrete sections. This can be accomplished using the tabsetPanel()
function.
fluidPage(titlePanel("Tabset layout"), sidebarLayout(sidebarPanel(),
mainPanel(tabsetPanel(tabPanel("tab1"), tabPanel("tab2"),
tabPanel("tab3")))))
10.3.4.4 Shiny Dashboard.
A dashboard has three parts: a header, a sidebar, and a body. Here’s the most minimal possible UI for a dashboard page.
You can learn more about customizing dashboards HERE
## ui.R ##
library(shinydashboard)
dashboardPage(dashboardHeader(), dashboardSidebar(), dashboardBody())
HTML content
The appearance of a Shiny app can be customized by using HTML content such as text and images. We can add HTML content with the shiny::tags
object. tags
is a list of functions that build specific HTML content. The names of the tag functions can be seen with names(tags)
. Some examples of tag functions, and the output they create include:
h1()
: first level header,h2()
: second level header,strong()
: bold text,em()
: italicized text,a()
: link to a webpage,img()
: image,br()
: line break,hr()
: horizontal line,div()
: division of text with a uniform style.
We can use any of these tag functions by subsetting the tags
list. For example,
to create a first level header we can write
tags$h1("Header 1")
,to create a link to a webpage we can write
tags$a(href = "www.webpage.com", "Click here")
,to create a section in an HTML document we can use
tags$div()
.
The h1()
function is a wrapper for tags$h1()
, a()
is equivalent to tags$a()
, and div()
is equivalent to tags$div()
. However, most of the tag functions do not have equivalent helpers because they share a name with a common R function.
Additional information about tag functions can be found in Customize your UI with HTML and the Shiny HTML Tags Glossary.
10.6 Recommended extension packages
The following represents a selection of high quality shiny extensions that can help you get a lot more out of shiny :-
shinyWidgets - this package gives you many many more widgets that can be used in your app. Run
shinyWidgets::shinyWidgetsGallery()
to see a selection of available widgets with this package. See examples hereshinyjs - this is an excellent package that gives the user the ability to greatly extend shiny’s utility via a series of javascript. The applications of this package range from very simple to highly advanced, but you might want to first use it to manipulate the ui in simple ways, like hiding/showing elements, or enabling/disabling buttons. Find out more here
shinydashboard - this package massively expands the available ui that can be used in shiny, specifically letting the user create a complex dashboard with a variety of complex layouts. See more here
shinydashboardPlus - get even more features out of the shinydashboard framework! See more here
shinythemes - change the default css theme for your shiny app with a wide range of preset templates! See more here
There are also a number of packages that can be used to create interactive outputs that are shiny compatible.
DT is semi-incorporated into base-shiny, but provides a great set of functions to create interactive tables.
plotly is a package for creating interactive plots that the user can manipulate in app. You can also convert your plot to interactive versions via
plotly::ggplotly()
! As alternatives, dygraphs and highcharter are also excellent.