Shiny is a tool for building web apps with R. This allows a user to interact with a webpage, and have the content of the webpage be controlled by R. It is easy to get started with your first Shiny app, but Shiny is also very deep and can become very complicated. This tutorial is intended to highlight some of the general structure and features of Shiny to get you started.
The R-studio Shiny tutorials are very helpful https://shiny.rstudio.com/tutorial/
This is a list of Shiny Apps that recently won prizes in the first annual Shiny app contest https://blog.rstudio.com/2019/04/05/first-shiny-contest-winners/?utm_content=buffere0bd9&utm_medium=social&utm_source=twitter&utm_campaign=buffer
The code below shows an example of the major parts of a shiny app. The two major parts are th ui
and server
objects.
ui
stands for user interface, and in this section we define and layout how the webpage will look.
server
: when you deploy a shiny app a few things happen. a. a server somewhere in the world will host your shiny app, and allow other people to find the app on the internet b. a user somewhere in the world will go to the website and will begin running your app locally on their computer c. as the user interacts with app, we need to pass information back and forth between their computer and the web server.
The server object runs on the server side and handles inputs and outputs. For example, it takes inputs from the user, does something based on the input, and the return an output that modifies the webpage that the user is looking at.
library(shiny)
# USER INTERFACE
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# put web page elements here
),
mainPanel(
# put web page elements here
)
)
)
# SERVER
server <- function(input, output) {
# recieve inputs
# do things
# update the webpage
}
# Run the application
shinyApp(ui = ui, server = server)
library(shiny)
is placed at the beginning of the code, this loads the shiny package. If you want to use other packages, then load them here (at the beginning), before the ui
and server
objects are defined.
ui <- ...
this is where you define the User interface. This whole piece can get pretty long, especially when there are multiple pages, tabs, or other things on the webpage
fluidPage()
Shiny has many functions that make it “easy” to create webpage elements. Fluidpage is a system for setting up a webpage with different layouts. For example, inside this function we use the sideBarLayout()
sidedarLayout()
Sets up the ability to have a side panel (e.g., on the left or right of the page), and a main panel.
sidebarPanel()
this is where you put shiny widgets (or other html objects), and they will appear in the sidebar.
mainPanel()
this is where you put shiny widgets (or other html objects), and they will appear in the main panel of the website
server()
This is where you handle inputs that come in, do something based on the inputs, and then return something to the webpage as an output.
shinyApp()
runs the app.
Shiny comes with several “widgets” that can be put into the user interface.
This example shows the addition of a few widgets, and making a plot
library(shiny)
# USER INTERFACE
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# put web page elements here
# usually shiny widgets
actionButton("action1", label = "press me"),
actionButton("action2", label = "press me"),
sliderInput("slider1", label = h3("Slider"), min = 0,
max = 100, value = 50),
selectInput("select", label = h3("Select box"),
choices = list("Choice 1" = 1,
"Choice 2" = 2,
"Choice 3" = 3),
selected = 1)
),
mainPanel(
# put web page elements here
# usually to display things
plotOutput("plot1"),
plotOutput("plot2"),
textOutput("text1")
)
)
)
# SERVER
server <- function(input, output) {
# recieve inputs
# do things
# update the webpage
output$plot1 <- renderPlot({
hist(rnorm(100,0,1))
})
}
# Run the application
shinyApp(ui = ui, server = server)
Note the following:
The widgets are displayed in the sidebar, but they don’t do anything yet. They need to be “hooked up” on the server side
This app does create a plot and display it on the webpage.
plotOutput("plot1")
in the mainPanel creates an html object on the webpage capable of displaying a figure. This is an empty object at the beginningThis code in the server object makes a figure and then sends it to plot1
.
output$plot1 <- renderPlot({
hist(rnorm(100,0,1))
})
A bunch of things are happnening above. Inside the server object there is an output
object. This will contain the ids of output objects that are set up in the ui. We set up three output objects, with the ids plot1
, plot2
, and text1
. We can address them using the dollar sign. so output$plot1 <-
will try to put something into the plotOutput()
with the id plot1
.
Because plot1
is an id for a plotOutput()
, we need to send a plot object. We use renderPlot({})
for this. Inside the renderPlot({})
function, we simply write a line of R code that produces a figure. This gets “rendered” as a plot, and then sent to the plotOutput with the plot1 id. As a result, a plot is displayed on the webpage.
slider1
library(shiny)
# USER INTERFACE
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
#displays a slider
sliderInput("slider1",
label = h3("Slider"),
min = 0,
max = 100,
value = 50)
),
mainPanel(
# create a plotting object for the webpage
plotOutput("someplot"),
#create a textoutput
textOutput("sometext")
)
)
)
# SERVER
server <- function(input, output) {
# update plot
output$someplot <- renderPlot({
hist(rnorm(100,input$slider1,1))
})
output$sometext <- renderText({
input$slider1
})
}
# Run the application
shinyApp(ui = ui, server = server)
selectInput
to create a dropdown menulibrary(shiny)
# USER INTERFACE
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
#displays a dropdown with choices
selectInput("select", label = h3("Select box"),
choices = list("mpg" = "mpg",
"cyl" = "cyl",
"disp" = "disp"),
selected = "mpg")
),
mainPanel(
# create a plotting object for the webpage
plotOutput("someplot")
)
)
)
# SERVER
server <- function(input, output) {
# make a new plot every time button is clicked
output$someplot <- renderPlot({
hist(mtcars[,input$select])
})
}
# Run the application
shinyApp(ui = ui, server = server)
Same as above, only this time we automatically set the choices in the dropdown to be all of the column names in the mtcars dataframe.
library(shiny)
# USER INTERFACE
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
#displays a dropdown with choices
selectInput("select", label = h3("Select box"),
choices = setNames(names(mtcars),names(mtcars)),
selected = "mpg")
),
mainPanel(
# create a plotting object for the webpage
plotOutput("someplot")
)
)
)
# SERVER
server <- function(input, output) {
# make a new plot every time button is clicked
output$someplot <- renderPlot({
hist(mtcars[,input$select])
})
}
# Run the application
shinyApp(ui = ui, server = server)
Shiny implements a concept called reactivity. The basic idea is that some variables are “reactive” to changes.
Many things in Shiny are reactive by default. For example an input$id
is reactive. If the id points to an action button, that object automatically “reacts” or updates when the action button is clicked. If the id points to a choice in a dropdown menu, then the object will automatically update with the new choice. If somethingn depends on the reactive input, like a plotting object, then the plot will automatically be redrawn when the reactive input changes.
Shiny allows you to create your own reactive objects. This example shows the use of reactiveValues
. We create an object called d
, that is reactive d <- reactiveValues()
. This new variable will be like a list, we can add named items to it. For example, in the code below, when we click the button, we add a random sample of 10 numbers to d
, under the named item a
.
d$a <- rnorm(10,0,1)
Then, we use the observe
function. The observe function will detect any changes to reactive variables placed inside the function, and then do something automatically. In this case, whenever the contents of d$a
is changed, we print the contents of d$a
to the console.
observe({
print(d$a)
})
library(shiny)
# USER INTERFACE
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
# displays an action button
actionButton("action1", label = "press me")
),
mainPanel(
# create a plotting object for the webpage
plotOutput("someplot")
)
)
)
# SERVER
server <- function(input, output) {
d <- reactiveValues()
# make a new plot every time button is clicked
observeEvent(input$action1, {
output$someplot <- renderPlot({
hist(rnorm(100,0,1))
d$a <- rnorm(10,0,1)
})
})
observe({
print(d$a)
})
}
# Run the application
shinyApp(ui = ui, server = server)