install.packages("plotly")
Short introduction to interactive visualisation in R
This very short introduction to interactive visualisation in R will teach you:
- How to use
plotly
to create interactive visualisations from aggplot2
figure. - How to develop a simple interactive
shiny
application.
More specifically, for the shiny
application, you will learn about the two components of an application, namely the user interface and server, and how the reactive programming paradigm enables communication between them.
Interactive plots with plotly
Install the package with
The plotly
package can be used for creating interactive web graphics open source JavaScript graphing library plotly.js and its R binding.
Once a ggplot2
figure is stored in a variable such as p
below …
library("ggplot2")
data(iris)
<- ggplot(data = iris,
p aes(x = Sepal.Length, y = Sepal.Width, colour = Species)) +
geom_point()
… the variable can simply be pass to the ggploty()
function:
library("plotly")
ggplotly(p)
See the plotly for R book for more details and to learn how to build plotly plots from scratch in R.
Interactive apps with shiny
Install the package with
install.packages("shiny")
Quoting the shiny
package desciption:
Makes it incredibly easy to build interactive web applications with R.
As opposed to plotly
above, when using shiny
, one tends to aim for more complete, long-lasting applications, rather than transient visualisations.
A shiny
application is composed of a ui (user interface) and a server that exchange information using a programming paradigm called reactive programming: changes performed by the user to the ui trigger a reaction by the server and the output is updated accordingly.
In the ui: define the components of the user interface (such as page layout, page title, input options and outputs), i.e what the user will see and interact with.
In the server: defines the computations in the R backend.
The reactive programming is implemented through reactive functions, which are functions that are only called when their respective inputs are changed.
An application is run with the
shiny::runApp()
function, that takes the directory containing the ui and server as input.
Let’s build a simple example from scratch, step by step. This app, shown below, uses the faithful
data, describing the wainting time between eruptions and the duration of the reuption for the Old Faithful geyser in Yellowstone National Park, Wyoming, USA.
head(faithful)
eruptions waiting
1 3.600 79
2 1.800 54
3 3.333 74
4 2.283 62
5 4.533 85
6 2.883 55
It shows the distribution of waiting times along a histogram (produced by the hist
function) and provides a slider to adjust the number of bins (the breaks
argument to hist
).
The app can also be opened at https://lgatto.shinyapps.io/shiny-app1.
Creation of our fist shiny app
- Create a directory that will contain the app, such as for example
"shinyapp"
. - In this directory, create the ui and server files, named
ui.R
andserver.R
. - In the
ui.R
file, let’s defines a simple (fluid) page containing- a title panel with a page title;
- a layout containing a sidebar and a main panel
shinyUI(fluidPage(
titlePanel("My Shiny App"),
sidebarLayout(
sidebarPanel(
),mainPanel(
)
) ))
- In the
server.R
file, we define theshinyServer
function that handles the inputs (coming from the ui) and ouputs (returned back to the ui) … there are none at this stage, and the R logic.
shinyServer(function(input, output) {
})
- Let’s now add some items to the ui: a text input widget in the sidebar and a field to hold the text ouput.
shinyUI(fluidPage(
titlePanel("My Shiny App"),
sidebarLayout(
sidebarPanel(
textInput("textInput", "Enter text here:")
),mainPanel(
textOutput("textOutput")
)
) ))
- We can now populate the
shinyServer
function in theserver.R
file. Below, we add some R code defining how to manipulate the user-provided text and render it using a shinytextOuput
.
shinyServer(function(input, output) {
$textOutput <- renderText(paste("User-entered text: ",
output$textInput))
input })
- Let’s now add a plot in the main panel in
ui.R
and some code to draw a histogram inserver.R
:
shinyUI(fluidPage(
titlePanel("My Shiny App"),
sidebarLayout(
sidebarPanel(
textInput("textInput", "Enter text here:")
),mainPanel(
textOutput("textOutput"),
plotOutput("distPlot")
)
) ))
shinyServer(function(input, output) {
$textOutput <- renderText(paste("User-entered text: ",
output$textInput))
input$distPlot <- renderPlot({
output<- faithful[, 2]
x hist(x)
})
})
- We want to be able to control the number of breaks used to plot the histograms. We first add a
sliderInput
to the ui for the user to specify the number of bins, and then make use of that new input to parametrise the histogram.
shinyUI(fluidPage(
titlePanel("My Shiny App"),
sidebarLayout(
sidebarPanel(
textInput("textInput", "Enter text here:"),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),mainPanel(
textOutput("textOutput"),
plotOutput("distPlot")
)
) ))
shinyServer(function(input, output) {
$textOutput <- renderText(paste("User-entered text: ",
output$textInput))
input$distPlot <- renderPlot({
output<- faithful[, 2]
x <- seq(min(x), max(x), length.out = input$bins + 1)
bins hist(x, breaks = bins)
})
})
- The next addition is to add a menu for the user to choose a set of predefined colours (that would be a
selectInput
) in theui.R
file and use that new input to parametrise the colour of the histogramme in theserver.R
file.
shinyUI(fluidPage(
titlePanel("My Shiny App"),
sidebarLayout(
sidebarPanel(
textInput("textInput", "Enter text here:"),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
selectInput("col", "Select a colour:",
choices = c("steelblue", "darkgray", "orange"))
),mainPanel(
textOutput("textOutput"),
plotOutput("distPlot")
)
) ))
shinyServer(function(input, output) {
$textOutput <- renderText(paste("User-entered text: ",
output$textInput))
input$distPlot <- renderPlot({
output<- faithful[, 2]
x <- seq(min(x), max(x), length.out = input$bins + 1)
bins hist(x, breaks = bins, col = input$col)
})
})
- The last addition that we want is to visualise the actual data in the main panel. We add a
dataTableOutput
inui.R
and generate that table inserver.R
using arenderDataTable
rendering function.
## Define UI for application that draws a histogram
shinyUI(fluidPage(
## Application title
titlePanel("My Shiny App"),
## Sidebar with text, slide bar and menu selection inputs
sidebarLayout(
sidebarPanel(
textInput("textInput", "Enter text here:"),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
selectInput("col", "Select a colour:",
choices = c("steelblue", "darkgray", "orange"))
),
## Main panel showing user-entered text, a reactive plot and a
## dynamic table
mainPanel(
textOutput("textOutput"),
plotOutput("distPlot"),
dataTableOutput("dataTable")
)
) ))
## Define server logic
shinyServer(function(input, output) {
$textOutput <- renderText(paste("User-entered text: ",
output$textInput))
input
## Expression that generates a histogram. The expression is
## wrapped in a call to renderPlot to indicate that:
##
## 1) It is "reactive" and therefore should be automatically
## re-executed when inputs change
## 2) Its output type is a plot
$distPlot <- renderPlot({
output<- faithful[, 2] ## Old Faithful Geyser data
x <- seq(min(x), max(x), length.out = input$bins + 1)
bins
## draw the histogram with the specified number of bins
hist(x, breaks = bins, col = input$col, border = 'white')
})
$dataTable <- renderDataTable(faithful)
output
})
Single-file app
Instead of defining the ui and server in their respective files, they can be combined into list
<- fluidPage(...)
ui <- function(input, output) { ... } server
To be run as
shinyApp(ui = ui, server = server)
With RStudio
With RStudio, one can create an RStudion shiny project to automate the creationg of a directory with a single-file shiny application.
Session information
The source of this document is available at https://github.com/lgatto/interactive-vis-intro. This document was generated on Fri Jul 7 08:34:18 2023.
sessionInfo()
R version 4.3.0 (2023-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 22.04.2 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3; LAPACK version 3.10.0
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_GB.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_GB.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_GB.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C
time zone: Europe/Brussels
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] plotly_4.10.2 ggplot2_3.4.2
loaded via a namespace (and not attached):
[1] gtable_0.3.3 jsonlite_1.8.7 highr_0.10 dplyr_1.1.2
[5] compiler_4.3.0 tidyselect_1.2.0 tidyr_1.3.0 scales_1.2.1
[9] yaml_2.3.7 fastmap_1.1.1 R6_2.5.1 labeling_0.4.2
[13] generics_0.1.3 knitr_1.43 htmlwidgets_1.6.2 tibble_3.2.1
[17] munsell_0.5.0 pillar_1.9.0 rlang_1.1.1 utf8_1.2.3
[21] xfun_0.39 lazyeval_0.2.2 viridisLite_0.4.2 cli_3.6.1.9000
[25] withr_2.5.0 magrittr_2.0.3 crosstalk_1.2.0 digest_0.6.32
[29] grid_4.3.0 rstudioapi_0.14 lifecycle_1.0.3 vctrs_0.6.3
[33] evaluate_0.21 glue_1.6.2 data.table_1.14.8 farver_2.1.1
[37] fansi_1.0.4 colorspace_2.1-0 rmarkdown_2.23 purrr_1.0.1
[41] httr_1.4.6 ellipsis_0.3.2 tools_4.3.0 pkgconfig_2.0.3
[45] htmltools_0.5.5
Footnotes
You can for instance run this app with
runGitHub("interactive-vis-intro", "lgatto", subdir = "/src/shiny-app1")
↩︎