Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interactive plotting in shiny using mouse clicks

Tags:

r

shiny

I am doing a project where I use the shiny server and connect R to mongodb to fetch results from database and display it dynamically.

However, I face the following problem in it. I initially get the results from db and make a plot. After this plot is done, I want the user to make make two mouse clicks on the plot based on which it should take the two values as xlim and plot a zoomed version of the previous plot. However, I am not able to do it successfully.

Here is the code that I have written.

ui.R

library(shiny)
shinyUI(fluidPage(
    titlePanel("LOAD AND PERFORMANCE DASHBOARD"),

    sidebarLayout(
            sidebarPanel(
                    fluidRow(
                            selectInput("select", label = h3("Select type of testing"), 
                                        choices = list("Performance Testing"=1, "Capacity Testing"=2)),
                            radioButtons("radio", label = h3("Select parameter to plot"),
                                         choices = list("Disk" = 1, "Flit" = 2,"CPU" = 3,"Egress" =4,
                                                        "Memory" = 5))  
                    )),
            mainPanel(
                    plotOutput("plot",clickId="plot_click"),
                    textOutput("text1"),
                    plotOutput("plot2")
                    )
    )
))

server.R

library(shiny)
library(rmongodb)
cursor <- vector()
shinyServer(function(input, output) {

    initialize <- reactive({
            mongo = mongo.create(host = "localhost")
    })

    calculate <- reactive({
            if(input$radio==1)
                    xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "disk")
            else if(input$radio==2)
                    xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "flit")
            else if(input$radio==3)
                    xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "cpu")
            else if(input$radio==4)
                    xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "egress")
            else if(input$radio==5)
                    xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "memory")
    })

    output$plot <- renderPlot({
            initialize()
            value <- calculate()
            plot(value,xlab="Time",ylab="% Consumed")
            lines(value)
            cursor <- value
    })       

    output$text1 <- renderText({ 
            paste("You have selected",input$plot_click$x)
    })

    output$plot2 <- renderPlot({
            plot(cursor[cursor<input$plot_click$x && cursor>first_click ],xlab="Time",ylab="% Consumed")                lines(cursor)
            first_click <- input$plot_click$x
    })           

})

Thanks in advance for the help :)

like image 725
Ram Avatar asked Jan 19 '15 11:01

Ram


1 Answers

Here's a simple example that demonstrates the behavior you want, just run this code (or save as a file and source it). This code uses the new observeEvent function that debuted in Shiny 0.11, which just hit CRAN over the weekend.

The basic idea is that we track two reactive values, click1 and range. click1 represents the first mouse click, if any exists; and range represents the x-values of both mouse clicks. Clicking on the plot simply manipulates these two reactive values, and the plotting operation reads them.

library(shiny)

ui <- fluidPage(
  h1("Plot click demo"),
  plotOutput("plot", clickId = "plot_click"),
  actionButton("reset", "Reset zoom")
)

server <- function(input, output, session) {
  v <- reactiveValues(
    click1 = NULL,  # Represents the first mouse click, if any
    range = NULL    # After two clicks, this stores the range of x
  )

  # Handle clicks on the plot
  observeEvent(input$plot_click, {
    if (is.null(v$click1)) {
      # We don't have a first click, so this is the first click
      v$click1 <- input$plot_click
    } else {
      # We already had a first click, so this is the second click.
      # Make a range from the previous click and this one.
      v$range <- range(v$click1$x, input$plot_click$x)
      # And clear the first click so the next click starts a new
      # range.
      v$click1 <- NULL
    }
  })

  observeEvent(input$reset, {
    # Reset both the range and the first click, if any.
    v$range <- NULL
    v$click1 <- NULL
  })

  output$plot <- renderPlot({
    plot(cars, xlim = v$range)
    if (!is.null(v$click1$x))
      abline(v = v$click1$x)
  })
}

shinyApp(ui, server)
like image 150
Joe Cheng Avatar answered Sep 21 '22 14:09

Joe Cheng