1 of 53

Building Shiny Apps

Dean Attali�http://deanattali.com

@daattali

2 of 53

These slides are meant as a teaching aid for my Shiny tutorial:

http://deanattali.com/blog/building-shiny-apps-tutorial/

2

3 of 53

What is Shiny?

  • R package from RStudio

  • Web application framework for R

  • R code → interactive web page

  • No HTML/CSS/JavaScript knowledge required

  • Great for sharing R analysis with someone scared of R

3

4 of 53

Examples

4

5 of 53

What is a Shiny app?

Computer running R

Web page

5

6 of 53

What is a Shiny app?

User interface (UI)

Server code

6

7 of 53

Shiny app template

library(shiny)

ui <- fluidPage()

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

7

Important: Do not place any code after shinyApp(...)

8 of 53

Run Shiny app in RStudio, method 1

Save file as “app.R” → “Run” button turns to “Run App”

8

Good for creating Shiny apps quickly, all code in one file

9 of 53

Run Shiny app in RStudio, method 2

Save UI as “ui.R” and server as “server.R” in same directory

Good for complex Shiny apps, separates view vs logic

If using this method, do not include a call to shinyApp(...)

9

10 of 53

Run Shiny app in RStudio, method 3

File > New File > Shiny Web App...

Generates the template for you

10

11 of 53

Stop Shiny app in RStudio

Press “Esc” or click the Stop icon

11

12 of 53

Work through the tutorial

until the end of Section 4

12

13 of 53

Add elements to app inside fluidPage()

fluidPage(

h1("My Shiny app"),

"Hello STAT545"

)

library(shiny)

ui <- fluidPage("Hello STAT545")

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

13

ui

14 of 53

Add HTML to fluidPage()

  • Remember the UI simply creates HTML
  • Can use any HTML tags http://shiny.rstudio.com/articles/tag-glossary.html
  • h1() = header1, br() = line break, strong() = bold text
  • Any HTML tag can be accessed using `tags` object
    • h1 = tags$h1(), br = tags$br()
  • Common tags can be accessed without `tags`

14

15 of 53

Add HTML to fluidPage()

ui

fluidPage(

h1("My Shiny app"),� h3("Subtitle"),

"Hello",

"STAT545",�br(),�strong("bold text")

)

15

ui

16 of 53

Use a layout

  • By default, all elements stack up one after the other�
  • Can use different layouts http://shiny.rstudio.com/articles/layout-guide.html
  • We’ll use sidebarLayout()

16

17 of 53

Use a layout - sidebarLayout()

fluidPage(

titlePanel("My Shiny app"),

sidebarLayout(

sidebarPanel(

"This is a side panel"

),

mainPanel(

"And this is the main stuff"

)

)

)

17

ui

18 of 53

Use a layout - sidebarLayout()

18

titlePanel()

mainPanel()

sidebarPanel()

19 of 53

Work through the tutorial

until the end of Section 5

19

20 of 53

Inputs and outputs

  • For interactivity, app needs inputs and outputs
  • Inputs - things user can toggle
  • Output - R objects user can see, often depend on inputs

fluidPage(

# *Input() functions,

# *Output() functions

)

20

ui

21 of 53

Inputs

library(shiny)

ui <- fluidPage(

sliderInput(

"num", "Choose a number",

min = 0, max = 100,

value = 20)

)

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

21

22 of 53

Inputs

sliderInput("num", "Choose a number",

min = 0, max = 100, value = 20)

<div class="form-group shiny-input-container">

<label class="control-label" for="num">Choose a number</label>

<input class="js-range-slider" id="num" data-min="0" data-max="100" data-from="20" data-step="1" data-grid="true" data-grid-num="10" data-grid-snap="false" data-prettify-separator="," data-keyboard="true" data-keyboard-step="1" data-drag-interval="true" data-data-type="number"/>

</div>

22

23 of 53

Inputs

23

Colour input

colourpicker::colourInput()

24 of 53

Inputs

sliderInput("num", "Choose a number", min = 0, max = 100, value = 20)

*Input( inputId, label, ... )

?sliderInput

What arguments can I pass to an input function?

24

Input name

Label to display

Input-specific arguments

25 of 53

Work through the tutorial

until the end of Section 6

25

26 of 53

Outputs

  • Plots, tables, text - anything that R creates and users see
  • Initialize as empty placeholder space until object is created

26

Function

Outputs

plotOutput()

plot

tableOutput()

table

uiOutput()

Shiny UI element

textOutput()

text

27 of 53

Outputs

plotOutput("myplot", width = "300px")

?plotOutput

What arguments can I pass to an output function?

*Output( outputId, ... )

27

Output name

Output-specific arguments

28 of 53

Outputs

library(shiny)

ui <- fluidPage(

sliderInput("num", "Choose a number",

0, 100, 20),

plotOutput("myplot")

)

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

28

*Output() adds space for UI object

You need to build the object in server

29 of 53

Summary

library(shiny)

ui <- fluidPage()

server <- function(input, output) {}

shinyApp(ui = ui, server = server)

29

Begin app with template

Add elements as arguments to fluidPage()

Create inputs with *Input() functions

Create outputs with *Output() functions

Use server to assemble inputs into outputs

30 of 53

Two most common “why isn’t my app running?!” problems

Remember to:

  • comma-separate all the elements!
  • not add comma to the last element!

30

31 of 53

Work through the tutorial

until the end of Section 8

31

32 of 53

Server: assemble input into outputs

with 3 rules

server <- function(input, output) {

output$myplot <- renderPlot({

plot(rnorm(input$num))

})

}

32

33 of 53

Building outputs

1 - Save objects into output$

server <- function(input, output) {

output$myplot <- renderPlot({

plot(rnorm(input$num))

})

# in UI: plotOutput("myplot")

}

33

34 of 53

Building outputs

2 - Build objects with render*

server <- function(input, output) {

output$myplot <- renderPlot({

plot(rnorm(input$num))

})

}

34

35 of 53

*Output() → render*()

35

Output function

Render function

plotOutput()

renderPlot({})

tableOutput()

renderTable({})

uiOutput()

renderUI({})

textOutput()

renderText({})

36 of 53

render*() functions build reactive

output to display in UI

renderPlot({ plot(rnorm(100)) })

36

Code to build the object

Type of object to build

37 of 53

Building outputs

3 - Access input values with input$

server <- function(input, output) {

output$myplot <- renderPlot({

plot(rnorm(input$num))

# in UI:sliderInput("num", ...)

})

}

37

38 of 53

Using input$

input$num returns 25

input$num returns 50

input$num returns 75

38

39 of 53

Work through the tutorial

until the end of Section 9

39

40 of 53

Reactivity

  • Shiny uses reactive programming
  • Supports reactive variables
    • When value of variable x changes, anything that relies on x is re-evaluated
    • Contrast with regular R: �

x <- 5

y <- x + 1

x <- 10

# y is still 6

40

41 of 53

Reactivity

  • input$num is a reactive value

  • output$myplot depends on input$num
    • input$num changes → output$myplot reacts
  • All inputs are automatically reactive, so if you use any input inside a render* function, the output will re-render any time input changes

output$myplot <- renderPlot({

plot(rnorm(input$num))

})

41

42 of 53

Reactive contexts

  • You can define your own reactive variables
  • Reactive values can only be used inside reactive contexts
  • Any render* function is a reactive context
  • Use reactive({...}) to assign a reactive variable
  • Use observe({...}) to access a reactive variable
  • Remember: reactive variable means anything that depends on it gets re-executed automatically

42

43 of 53

Reactive contexts

Assign variable Access variable

server <- function(input, output) {

x <- input$num + 1

}

# error

server <- function(input, output) {

x <- reactive({

input$num + 1

})

}

# OK

server <- function(input, output) {

print(input$num)

}

# error

server <- function(input, output) {

observe({

print(input$num)

})

}

# OK

43

44 of 53

Simple Shiny app using basic reactivity

library(shiny)

ui <- fluidPage(

sliderInput("num", "Choose a number",

0, 100, 20),

plotOutput("myplot")

)

server <- function(input, output) {

output$myplot <- renderPlot({

plot(seq(input$num))

})

x <- reactive({

input$num + 1

})

observe({

print(x())

})

}

shinyApp(ui = ui, server = server)

Single file Two files

library(shiny)

fluidPage(

sliderInput("num", "Choose a number",

0, 100, 20),

plotOutput("myplot")

)

library(shiny)

function(input, output) {

output$myplot <- renderPlot({

plot(seq(input$num))

})

x <- reactive({

input$num + 1

})

observe({

print(x())

})

}

44

app.R

ui.R

server.R

45 of 53

Work through the tutorial

until the end of Section 10

45

46 of 53

Using buttons in the UI

  • Different from other inputs: you usually don’t care about the "value" of the button, you care when it’s clicked

ui <- fluidPage(

actionButton("btn", "Click me")

)

server <- function(input, output, session) {

observe({

cat(input$btn)

})

}

shinyApp(ui = ui, server = server)

46

47 of 53

Work through the tutorial

until the end of Section 12

47

48 of 53

Share your app: shinyapps.io

  • Go to http://www.shinyapps.io/ and make an account
  • Make sure all your app files are in an isolated folder
  • Click “Publish Application” in RStudio
    • You might be asked to install a couple packages���
    • Follow instructions from RStudio

48

49 of 53

Work through the tutorial

until the end of Section 13

49

50 of 53

PS. Shiny in Rmarkdown

  • Set output: html_document
  • Set runtime: shiny
  • You can now use interactive inputs/outputs in Rmarkdown!

---

output: html_document

runtime: shiny

---

```{r echo=FALSE}

sliderInput("num", "Choose a number",

0, 100, 20)

renderPlot({

plot(seq(input$num))

})

```

50

51 of 53

PPS. More things to check out

  • ?conditionalPanel - conditionally show UI elements
  • global.R - objects here are available to both ui.R and server.R
  • Use navbarPage() or tabsetPanel() for multiple tabs in UI
  • Use DT::dataTableOutput() instead of tableOutput() for an interactive table instead of ugly static table
  • Add images by placing image under “www/image.png” and using UI function img(src = "image.png")
  • Use update*Input() functions to update input values from R
  • Know JavaScript/CSS? Use includeScript() or includeCSS()

51

52 of 53

Recommended add-on packages to Shiny

  • leaflet (http://rstudio.github.io/leaflet/)
    • Add interactive maps to your apps
  • shinyjs (https://github.com/daattali/shinyjs)
    • Enhance user experience in Shiny apps
  • shinythemes (http://rstudio.github.io/shinythemes/)
    • Easily alter the appearance of your app
  • ggvis (http://ggvis.rstudio.com/)
    • Similar to ggplot2 but plots are web-based and more interactive
  • shinydashboard (https://rstudio.github.io/shinydashboard/)
    • Gives you tools to create “dashboards”

52

53 of 53

Awesome non-intimidating resources

53