Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to initialize brush in ggplot in a shiny app?

Tags:

r

ggplot2

shiny

I have a shiny app and I want a ggplot with a brush at the start, so the user does not need to select certain area of interest every time the app starts. Later of course user can select different area. Here is an example to start with:

library(shiny)
library(ggplot2)

runApp(shinyApp(
  ui = fluidPage(plotOutput('plotA', brush = brushOpts(id = 'plotA_brush')),
                 plotOutput('plotZ')),
  server = function(input, output, session) {
    pollData <- reactivePoll(60 * 1000, session,
                             checkFunc = function(){ Sys.time() },
                             valueFunc = function(){ data.frame(x = 1:100, y = cumsum(rnorm(100)))})
    output$plotA <- renderPlot({
      dt <- pollData()
      ggplot(dt, aes(x, y)) + geom_line()
    })
    ranges <- reactiveValues(x = NULL, y = NULL)
    observe({
      brush <- input$plotA_brush
      if(!is.null(brush)) {
        ranges$x <- c(brush$xmin, brush$xmax)
        ranges$y <- c(brush$ymin, brush$ymax)
      } else {
        ranges$x <- NULL
        ranges$y <- NULL
      }
    })
    output$plotZ <- renderPlot({
      dt <- pollData()
      ggplot(dt, aes(x, y)) + geom_line() + coord_cartesian(xlim = ranges$x, ylim = ranges$y)
    })
  }
))
like image 602
danas.zuokas Avatar asked Mar 25 '16 08:03

danas.zuokas


People also ask

Can you use ggplot2 in shiny?

With the Learn ggplot2 Shiny app, users can make plots using ggplot2 without having to code each step, reducing typos and error messages and allowing users to become familiar with ggplot2 code.

Why use Shiny modules?

Shiny modules have two big advantages. Firstly, namespacing makes it easier to understand how your app works because you can write, analyse, and test individual components in isolation. Secondly, because modules are functions they help you reuse code; anything you can do with a function, you can do with a module.


1 Answers

Yes, it is possible.

In the code below I've added just a few lines. First, I've added set.seed(42) so that the graphics are reproducible. Second, there is a dput(brush) that has been commented out. This was helpful for identifying the initial brush that I wanted to have. Lastly, The in the observe environment controlling the ranges I have added a if else set to use the default brush is it is a NULL value from the input$plotA_brush object.

library(shiny)
library(ggplot2)
set.seed(42)

runApp(shinyApp(
  ui = fluidPage(plotOutput('plotA', brush = brushOpts(id = 'plotA_brush')),
                 plotOutput('plotZ')),
  server = function(input, output, session) {


    pollData <- reactivePoll(60 * 1000, session,
                             checkFunc = function(){ Sys.time() },
                             valueFunc = function(){ data.frame(x = 1:100, y = cumsum(rnorm(100)))})
    output$plotA <- renderPlot({
      dt <- pollData()
      ggplot(dt, aes(x, y)) + geom_line()
    })
    ranges <- reactiveValues(x = NULL, y = NULL)
    observe({
      if (is.null(input$plotA_brush)) {
        brush <- structure(list(xmin = 14.313925002001, xmax = 39.942241912585, ymin = 1.1077251080591, ymax = 5.5028180250535, mapping = structure(list( x = "x", y = "y"), .Names = c("x", "y")), domain = structure(list( left = -3.95, right = 104.95, bottom = -4.07771077213569, top = 9.69030145758825), .Names = c("left", "right", "bottom", "top")), range = structure(list(left = 32.3904099935947, right = 674.020527857828, bottom = 368.859578048224, top = 5.47945189149413), .Names = c("left", "right", "bottom", "top")), log = structure(list(x = NULL, y = NULL), .Names = c("x", "y")), direction = "xy", brushId = "plotA_brush", outputId = "plotA"), .Names = c("xmin", "xmax", "ymin", "ymax", "mapping", "domain", "range", "log", "direction", "brushId", "outputId"))
      } else {
        brush <- input$plotA_brush
      }
      # dput(brush)  # Useful for finding the initial brush
      if(!is.null(brush)) {
        ranges$x <- c(brush$xmin, brush$xmax)
        ranges$y <- c(brush$ymin, brush$ymax)
      } else {
        ranges$x <- NULL
        ranges$y <- NULL
      }
    })
    output$plotZ <- renderPlot({
      dt <- pollData()
      ggplot(dt, aes(x, y)) + geom_line() + coord_cartesian(xlim = ranges$x, ylim = ranges$y)
    })
  }
))

The initial starting page looks like this:

enter image description here

like image 167
Peter Avatar answered Oct 13 '22 00:10

Peter