install.packages(c("flexdashboard", "DT", "shiny"))
Pre-lecture materials
Read ahead
Before class, you can prepare by reading the following materials:
- Information about creating dashboards: https://pkgs.rstudio.com/flexdashboard
- Examples of
flexdashboard
dashboards: https://pkgs.rstudio.com/flexdashboard/articles/examples
Prerequisites
Before starting you must install three additional packages:
flexdashboard
- this provides tools for easily building dashboardsDT
- this provides built-in data display functionalityshiny
- this provides functionality to create interactive dashboard elements
You can do this by calling
or use the “Install Packages…” option from the “Tools” menu in RStudio.
Acknowledgements
- “R for Data Science” by Grolemund and Wickham, sections 29.6 and 29.7.2. It is based on lecture notes initially developed by Margaret Taub and Leah Jager.
- https://epirhandbook.com/en/dashboards-with-r-markdown.html
Learning objectives
At the end of this lesson you will:
- Know how to create a basic dashboard to display data analysis elements using
flexdashboard
- Add interactive elements to your dashboard using tools from the
shiny
package - Have resources to assist you in developing your own more complex dashboard to clearly present data and interactive elements
Introduction
If we were not familiar with data dashboards before the pandemic, many of us learned just how useful they are for displaying data in a way that is visual, concise and easy to update.
Dashboards like JHU’s COVID-19 trackers were an amazing resource for anyone interested in understanding more about the progression of the pandemic, from cases to vaccine rates to emerging variants. One of the creators, Lauren Gardner, recently won a prestigious award for her work, acknowledging the importance of good data communication to the broad public to improve public health.
Data dashboards allow you to communicate large amounts of information visually and quickly with the added benefit of allowing the user to interact with the data directly in the dashboard.
flexdashboard
is a method of creating dashboards using R Markdown with panels and pages. The dashboard content can be
- text
- static figures/tables
- interactive graphics
flexdashboard
- It requires minimal non-standard R coding - with very little practice you can quickly create a dashboard.
- The dashboard can usually be emailed to colleagues as a self-contained HTML file - no server required.
- You can combine flexdashboard with
shiny
,ggplotly
, and other “html widgets” to add interactivity.
flexdashboard
- Less customization as compared to using shiny alone to create a dashboard
Examples
Here’s an example of what a flexdashboard
might look like:
For more examples of flexdashboard
dashboards, check out here:
Getting started
To author a flexdashboard
you create an R Markdown document within RStudio using the New R Markdown dialog:
To create a new dashboard, use the menus at the top of RStudio:
- Select File
- Select New File
- Select R Markdown…
- Choose From Template in the box on the left
- Select Flex Dashboard from the box on the right
- Then click OK
This will open up a dashboard template.
This option will only appear once you have installed the flexdashboard
package.
You can knit this file just as you would a regular R Markdown document.
Let’s try this out. We will:
- Create a new Project in RStudio.
- Create a new R Markdown with the
flexdashbard
template following instructions above. - Knit the file and take a look at what we get!
Note: you will have to save this file first before knitting. Save it in your project directory as trial_dashboard.Rmd
when prompted.
Flexdashboard
A quick view
Let’s explore the R Markdown a bit.
YAML
Similar to other R Markdown and Quarto documents, there is a YAML at the top of the file. The YAML parameter output:
is required and specifies the type of file to be produced (e.g. html_document
, pdf_document
, word_document
, or powerpoint_presentation
).
For flexdashboard, output
must be set as output:flexdashboard::flex_dashboard
, which is a bit confusing looking.
To make thing even more confusing, there is often an additional colon and indented sub-parameter (see orientation:
and vertical_layout:
parameters below).
: "Untitled"
title:
output::flex_dashboard:
flexdashboard: columns
orientation: fill vertical_layout
- Two spaces are important to define the subparameters.
- Use an additional colon after things like
key:value
if you want to further define subparameters. - If appropriate, logical values should be given in YAML in lowercase (
true
,false
,null
).
Code chunks and text
Similar to other R Markdown files, these files also can contain multiple code chunks.
They are structured in the same way you would structure them with three back-ticks and curly brackets with a lowercase “r” within.
You can write narrative text similarly as well with all the markdown syntax you are already familiar with with italics, bold, bullets, numbering, etc.
Headings
Notice the layout of the blank document is given by the hash (#) signs. In general:
- Each level 1 header (#) begins a new page in the dashboard.
- Each level 2 header (##) begins a new column or a row depending on your
orientation:
parameter. - Each level 3 header (###) create panels for plots, charts, tables, text, etc.
# First-level heading (page)
## Second level heading (row or column)
### Third-level heading (pane for plot, chart, etc.)
In our blank document, you see the blank output with the title: "Untitled"
and then three rows of charts (Chart A, Chart B, and Chart C.
The code in the three sections with these three titles are all blank.
Section attributes
Another thing you might notice is that you can specify section attributes to apply to parts of the dashboard in a key=value
structure after the heading and within curly brackets { }
.
For example, the {data-width=}
and {data-height=}
attributes set relative size of charts, columns, rows laid out in the same dimension (horizontal or vertical).
## Column {data-width=650}
- These attributes are written after a heading in a text portion of the script.
- These are different than the knitr options inserted within at the top of R code chunks, such as
out.height =
.
Some section attributes specific to flexdashboard include:
{data-orientation=}
Set to eitherrows
orcolumns
. If your dashboard has multiple pages, add this attribute to each page to indicate orientation.
{data-width=}
and{data-height=}
set relative size of charts, columns, rows laid out in the same dimension (horizontal or vertical).- Height of charts also depends on whether you set the YAML parameter
vertical_layout: fill
orvertical_layout: scroll
. If set to scroll, figure height will reflect the traditionalfig.height =
option in the R code chunk.
- See complete size documentation at the flexdashboard website
- Height of charts also depends on whether you set the YAML parameter
{.hidden}
Use this to exclude a specific page from the navigation bar
{data-navbar=}
Use this in a page-level heading to nest it within a navigation bar drop-down menu. Provide the name (in quotes) of the drop-down menu. See example below.
For the next 5 minutes, pair up with a partner (or try it alone) and explore the template dashboard and adjust the layout in the following ways:
- Try adding pages, columns/rows, and charts with R Markdown headings (e.g. #, ##, or ###)
- Adjust the orientation using the YAML parameter
orientation:
to eitherrows
orcolumns
- Specify whether the layout fills the browser or allows for a scrolling layout
- Add tabs to a particular section heading using the
{.tabset}
attribute - Add a navigation menu or side bar using the
{data-navmenu}
attribute or the{.sidebar}
attribute, respectively.
Be sure to open the resulting dashboard in a browser window to really see it; you won’t be able to view it very well in the small viewer pane within RStudio.
Diamonds dashboard
There are several example dashboards included in the folder containing today’s lecture.
Here is is a dashboard using the diamonds
dataset in the ggplot2
package:
---
title: "Diamonds distribution dashboard"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
---
```{r setup, include = FALSE}
library(ggplot2)
library(dplyr)
knitr::opts_chunk$set(fig.width = 5, fig.asp = 1/3)
```
## Column 1
### Carat
```{r}
diamonds |>
ggplot(aes(carat)) +
geom_histogram(binwidth = 0.1)
```
### Cut
```{r}
diamonds |>
ggplot(aes(cut)) +
geom_bar()
```
### Colour
```{r}
diamonds |>
ggplot(aes(color)) +
geom_bar()
```
## Column 2
### The largest diamonds
```{r}
diamonds %>%
arrange(desc(carat)) %>%
head(100) %>%
select(carat, cut, color, price) %>%
DT::datatable()
```
Above, you can see there are two columns (designated by ##) and various rows within each column (designated with ###).
This code relies on the DT
package, which is an interface to the DataTables JavaScript library.
The DT
package provides a nice way to display R matrices or data frames as interactive HTML tables that support filtering, pagination, and sorting.
For the next 5 minutes, pair up with a partner (or try it alone), open the file Diamond_dashboard_example.Rmd
and knit it. Explore to see if you can make the following changes:
- Can you change the titles of each of the graphs in the column on the left?
- How could you change the first graph on the left to be a histogram of prices instead of carats?
- Or could you add a fourth graph to the dashboard that shows price?
Note that to get access to the diamonds
dataset that the dashboard uses, you will have to have loaded the ggplot2
package, which is part of the tidyverse
. You can see that the dashboard uses this package by looking at the first set-up code chunk in the dashboard .Rmd file.
Shiny
Thus far, we have used flexdashbard
. Now we will talk about how integrating the R package shiny
can make your dashboard even more reactive to user input.
For example, a use can change something in the dashboard (e.g. a date range or filter for a specific subset of the data) and they will see the results immediately without needing to re-knit the document.
You can use shiny to produce apps/dashboards without flexdashboard too.
The Shiny basics gives an overview and includes primers on shiny syntax, app file structure, and options for sharing/publishing. Generally, these syntax translate to flexdashboard as well.
Embedding shiny in flexdashboard is however, a fundamental change to your flexdashboard. It will no longer produce an HTML output that you can send by email and anyone could open and view.
Instead, it will be an “app”. The “Knit” button at the top of the script will be replaced by a “Run document” icon, which will open an instance of the interactive the dashboard locally on your computer.
Sharing your dashboard will now require that you either:
- Send the Rmd script to the viewer, they open it in R on their computer, and run the app, or
- The app/dashboard is hosted on a server accessible to the viewer (most typical scenario)
Thus, there are benefits to integrating shiny, but also complications.
Shiny documents need to be deployed to a Shiny Server to be shared broadly.
See instructions for creating a free account at http://www.shinyapps.io/ and instructions on how to publish to the web.
Settings
To embed shiny reactivity into flexdashboard, you need only make a few changes to your flexdashboard R Markdown script.
Specifically, you need to add the YAML parameter runtime: shiny
at the same indentation level as output:
, as below:
---
title: "Outbreak dashboard (Shiny demo)"
output:
flexdashboard::flex_dashboard:
orientation: columns
vertical_layout: fill
runtime: shiny
---
It is also convenient to enable a “side bar” to hold the shiny input widgets that will collect information from the user.
Create a column and indicate the {.sidebar}
option to create a side bar on the left side.
You can add text and R chunks containing the shiny input
commands within this column.
If your app/dashboard is hosted on a server and may have multiple simultaneous users, name the first R code chunk as global
.
- Include the commands to import/load your data in this chunk.
- This special named chunk is treated differently, and the data imported within it are only imported once (not continuously) and are available for all users.
- This improves the start-up speed of the app.
Shiny syntax
You can have input that is text, numeric, selecting from a menu, or checking a box, as shown below. (Don’t run this code, it’s just there to show you what the syntax looks like!)
textInput("name", "What is your name?")
numericInput("age", "How old are you?", NA, min = 0, max = 150)
selectInput("variable", "Variable:",
c("Cylinders (cyl)" = "cyl",
"Transmission (am)" = "am",
"Gears (gear)" = "gear"))
checkboxInput("outliers", "Show outliers", TRUE)
What is happening above?
The first argument
The input values are stored in the object given by the first argument of these input functions. For example,
- The text input is stored in an object called
name
- The numeric input is stored in an object called
age
You can then refer to the values with input$name
and input$age
, and the code that uses them will be automatically re-run whenever they change.
The second argument
The second argument gives the text that is displayed to the user to prompt their input. For example,
- The input area for
name
will show “What is your name?” and so on.
Later arguments for each type give additional information about that input, such as minimum and maximum allowed values for numeric input and menu options for the select input.
To add Shiny components to a flex dashboard you will want to do the following:
- Add
runtime: shiny
to the YAML header at the top of the document. - Add the
{.sidebar}
attribute to the first column of the dashboard to make it a host for Shiny input controls (note this step isn’t strictly required, but many Shiny based dashboards will want to do this). - Add Shiny inputs and outputs as appropriate using the input functions.
- When including plots, be sure to wrap them in a call to
renderPlot
. This is important not only for dynamically responding to changes but also to ensure that they are automatically re-sized when their container changes.
Examples
There are a couple examples of simple flex dashboards that use Shiny in the following files that are included with this lecture.
Open each one of these files and run it by clicking the “Run document” button that is where the “Knit” button usually is.
Shiny apps must be run rather than knitted, but the idea is the same! Be sure to open the output in a browser tab.
Geyser dashboard
Here is a dashboard using the faithful
dataset in base R, which contains the waiting time between eruptions and the duration of the eruption for the Old Faithful geyser in Yellowstone National Park, Wyoming, USA.
---
title: "Old Faithful Eruptions"
output:
flexdashboard::flex_dashboard:
orientation: columns
runtime: shiny
---
```{r global, include=FALSE}
# load data in 'global' chunk so it can be shared by all users of the dashboard
library(datasets)
data(faithful)
```
## Column {.sidebar}
Waiting time between eruptions and the duration of the eruption for the
Old Faithful geyser in Yellowstone National Park, Wyoming, USA.
```{r}
selectInput("n_breaks", label = "Number of bins:",
choices = c(10, 20, 35, 50), selected = 20)
sliderInput("bw_adjust", label = "Bandwidth adjustment:",
min = 0.2, max = 2, value = 1, step = 0.2)
```
## Column
### Geyser Eruption Duration
```{r}
renderPlot({
hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(input$n_breaks),
xlab = "Duration (minutes)", main = "Geyser Eruption Duration")
dens <- density(faithful$eruptions, adjust = input$bw_adjust)
lines(dens, col = "blue")
})
```
For the next 5 minutes, pair up with a partner (or try it alone) and explore Geyser flexdashboard, which includes interactive elements from Shiny.
- Play with the user input options in the left hand sidebar to see how the user can interact with the data through the dashboard.
- Then look at both the code and the output to see how the code relates to what is shown in the dashboard.
- Play around with the options in the code chunks to see if you can get a sense of what they are doing.
Mile per gallon dashboard
One thing to point out in the MPGFlexDashboard.Rmd
file is the following chunk of code:
<- reactive({
formulaText paste("mpg ~", input$variable)
})
This chunk of code allows the title of the graph to change depending on the input given by the user.
It uses the reactive()
function to specify that the text is not static but will change depending on what is selected by the user.
You can see here the object formulaText
will contain text consisting of pasting together “mpg ~” and the variable value selected from the user in the drop-down menu.
Then, this formulaText
object is used as the title in the plot! And even more importantly, it is used in the call to the boxplot
function, to determine which variable to display in the plot.
Super cool!
Getting started with Project 4
For Project 4, you will need to build and deploy a dashboard. Here are some instructions and some example dashboards to help get you started.
Deploying a dashboard
Here are some helpful pointers for getting a free Shinyapps.io
account and then publishing your dashboard to the web:
- Sign up for a free account on http://www.shinyapps.io/
- Within RStudio, install the rsconnect package:
install.packages("rsconnect")
- Within RStudio Cloud, select “Tools” then “Global Options…” and then select “Publishing” from the left-hard menu. (Within the non-cloud RStudio, under the “Preferences” menu, click on “Publishing”.) Click the “Connect” button next to the publishing accounts box and then “Shinypps.io” to link your shinyapps.io account to your RStudio. Click on “Shinyapps.io” from the pop-up menu, and then follow the instructions to link your account. This involves copying and pasting a token from your account into the box in R Studio.
- Now you are ready to publish! Click the “Run Document” button to create your app; then click “Publish” in the upper right hand corner of your app (the publish icon is a blue circle with blue curves around it). Choose “Publish just this document” from the pop-up menu. Make sure the selected destination account is your shinyapps.io account. You can change the name of the app if you want. Then click publish!
- If you want to delete the app (unpublish it), you need to do this from within your shinyapps.io account. Go to http://www.shinyapps.io/ and log in to your account. Click on applications to manage your applications. You must first archive your app before you can delete it.
Stephanie’s dashboard
I have deployed the Old Faithful dashboard to my own Shiny account and linked the public github repo (on GitHub Classroom) to give as an example:
- Deployed dashboard: https://stephaniehicks.shinyapps.io/OldFaithfulGeyser
- GitHub repository: https://github.com/jhu-statprogramming-fall-2023/biostat777-project4-stephaniehicks
Some example dashboards from last year
Post-lecture materials
Final Questions
Here are some post-lecture questions to help you think about the material discussed.
- Starting with the
GeyserFlexDashboard.Rmd
file, modify the file to also create a data display related to thewaiting
variable. This display could be on another tab, or you could create an entire new page. You could allow the user to specify if they want a histogram or a boxplot with a dropdown selector. - Alternatively, keep the layout simple with a single pane for the plot, but allow the user to select whether they want to display a histogram of the
waiting
variable or theeruptions
variable. Make sure to update the main plot label to indicate the selected variable. - Similar modifications can be made to the
MPGFlexDashboard.Rmd
example. Create an interface that allows the user to select two different variables from thempg
data set and then create an appropriate data display to illustrate the relationship between these two variables, updating any plot labels to reflect the selected variables.
Additional Resources
Here are a list of resources on Shiny (more involved than Flex Dashboard):
- Main page: http://shiny.rstudio.com
- Awesome tutorial: http://shiny.rstudio.com/tutorial/
- An example app that Ruthe (former Biostats ScM student) made in a class: https://gunben.shinyapps.io/Pneumonia426/