Bioconductor Developer Day, 2016: Shiny Gadgets and Interactive Base Graphics

Sean Davis

2016-06-24

Shiny

  • interactively communicating ideas and results
    • plots
    • data
    • model fitting
  • for full application development
    • interact with data sources
    • collect and react to input

Gadgets vs Apps

  • Gadgets are interactive tools that enhance the developer analyst experience
  • Apps represent the output of an analsys, Gadgets are for using during an analysis
  • The audience for an App is the end user, while the audience for a Gadget is an R user
  • Gadget fundamentals are shiny, but design is focused
    • on limited screen space
    • on useful functionality during analysis
    • performing a function or returning results
  • Apps run on Shiny Server, while Gadgets are intended to be invoked in code

Gadgets

Shiny Gadgets could be created for most any task you might do during data loading, cleaning, manipulation, and visualization.

  • A tool to preview regular expressions for find/replace (sub and gsub)
  • Visual selection tools for subsetting or outlier exclusion
  • An easy-to-use UI for downloading data from a complicated API and turning it into a data frame

Gadget structure

library(shiny)
library(miniUI)

myGadgetFunc <- function(inputValue1, inputValue2) {
  ui <- miniPage(
    ## Define layout, inputs, outputs, etc.
  )
  
  server <- function(input, output, session) {
    # Define reactive expressions, outputs, etc.
    # And then 
    stopApp(returnValue)
  }
  runGadget(ui, server)
}

Gadget UI block

  ui <- miniPage(
    gadgetTitleBar("My Gadget"),
    miniContentPanel(
      # Define layout, inputs, outputs
    )
  )

Gadget Server block

  server <- function(input, output, session) {
    # Define reactive expressions, outputs, etc.

    # When the Done button is clicked, return a value
    observeEvent(input$done, {
      returnValue <- ...
      stopApp(returnValue)
    })
  }

regex test example

regexTest = function(pattern="night", 
                     x = "We can turn day into night with this Gadget",
                     replace = "day") {
  
  ui = miniPage(
    gadgetTitleBar("Basic gsub tester"),
    miniContentPanel(
      textInput("text","Text:", x),
      textInput('pattern','Pattern to replace:', pattern),
      textInput("replacement","Text to substitute", replace),
      textOutput("out")
    )
  )
  
  server = function(input, output, session) {
    output$out = renderText( gsub(pattern = input$pattern,
                                 replace = input$replacement, 
                                 x = input$text) )
    observeEvent(input$done, {
      returnValue <- input$pattern
      stopApp(returnValue)
    })
  }
  runGadget(ui, server)
}

ggbrush example

ggbrush <- function(dframe, xvar, yvar, viewer=paneViewer()) {
  
  ui <- miniPage(
    gadgetTitleBar("Drag to select points"),
    miniContentPanel(
      # The brush="brush" argument means we can listen for
      # brush events on the plot using input$brush.
      plotOutput("plot", height = "100%", brush = "brush")
    )
  )
  
  server <- function(input, output, session) {
    
    # Render the plot
    output$plot <- renderPlot({
      # Plot the data with x/y vars indicated by the caller.
      ggplot(dframe, aes_string(xvar, yvar)) + geom_point()
    })
    
    # Handle the Done button being pressed.
    observeEvent(input$done, {
      # Return the brushed points. See ?shiny::brushedPoints.
      stopApp(brushedPoints(dframe, input$brush))
    })
  }

  runGadget(ui, server)
}

Wrapping shiny

shinyFunction = function() {
  require(shiny)
  server <- function(input, output) {
    output$distPlot <- renderPlot({
      hist(rnorm(input$obs), col = 'darkgray', border = 'white')
    })
  }
  
  ui <- fluidPage(
    sidebarLayout(
      sidebarPanel(
        sliderInput("obs", "Number of observations:", min = 10, max = 500, value = 100)
      ),
      mainPanel(plotOutput("distPlot"))
    )
  )
  
  shinyApp(ui = ui, server = server)
}

Complex Shiny Wrap

shinyFunction = function() {
  runApp(system.file("MyPackage","shinyAppDir"))
}

Further reading