简体   繁体   中英

Change plot based on click input in R shiny

For my app, I need the user to click an area on a plot, then the plot responds to that click and shows a new plot that is linked to that input click.

However, currently it runs, but the new plot only displays for 3 seconds and then goes back to the original plot. I found a similar example here . This plot updates based on a list of reactiveValues then draws those new points the user selected. I think if I find a way to modify it to draw the new plot immediatly after the clicked event it should work, but stuck on this part.

So ideally the below example will add the new point immediatly after beind clicked. In my case I will need to display the new plot until a new area of the plot is clicked.

Example from the link

library(shiny)

ui <- basicPage(
  plotOutput("plot1", click = "plot_click"),
  verbatimTextOutput("info"),
  actionButton("updateplot", "Update Plot:")
)

server <- function(input, output) {
  val <- reactiveValues(clickx = NULL, clicky = NULL)

  observe({
    input$plot_click
    isolate({
      val$clickx = c(val$clickx, input$plot_click$x)
      val$clicky = c(val$clicky, input$plot_click$y)     
    })
  }) #adding clicks to list

  output$plot1 <- renderPlot({
    plot(mtcars$wt, mtcars$mpg)
    input$updateplot
    isolate({
      points(val$clickx, val$clicky)
    })
  })

  output$info <- renderText({
    paste0("x = ", val$clickx, ", y = ",val$clicky, "\n")
  })

}

shinyApp(ui, server)

This example shows a main plot and upon click in the main plot it shows a sub plot. Once clicked again it shows again the main plot.

The idea is that a counter ( trigger ) is increased whenever a click happens. It is important to use req(.) in the observer, lest the observer fires again when the mouse button is released (in this case input$plot_click is set to NULL ).

The renderPlot(.) then takes a dependency on this trigger and shows either the main or the sub plot.

Update. If you want to use info from the input$plot_click object you should save it as well, to avoid that it get NULL .

library(shiny)
library(ggplot2)

ui <- basicPage(
   plotOutput("plot1", click = "plot_click")
)

server <- function(input, output) {
   plot_data <- reactiveValues(trigger = 0, x = NA, y = NA)

   observe({
      req(input$plot_click)
      isolate(plot_data$trigger <- plot_data$trigger + 1)
      plot_data$x <- input$plot_click$x
      plot_data$y <- input$plot_click$y
    })

   output$plot1 <- renderPlot({
      if (plot_data$trigger %% 2 == 0) {
         plot(1:10, main = "Main Plot")
      } else {
         ggplot() + geom_point(aes(x = plot_data$x, y = plot_data$y), size = 5, shape = 19)
      }
   })
}

shinyApp(ui, server)

Just drop the isolate in your renderPlot:

library(shiny)

ui <- basicPage(
  plotOutput("plot1", click = "plot_click"),
  verbatimTextOutput("info")
)

server <- function(input, output) {
  val <- reactiveValues(clickx = NULL, clicky = NULL)

  observe({
    input$plot_click
    isolate({
      val$clickx = c(val$clickx, input$plot_click$x)
      val$clicky = c(val$clicky, input$plot_click$y)     
    })
  }) #adding clicks to list

  output$plot1 <- renderPlot({
    plot(mtcars$wt, mtcars$mpg)
    points(val$clickx, val$clicky)
  })

  output$info <- renderText({
    paste0("x = ", val$clickx, ", y = ",val$clicky, "\n")
  })

}

shinyApp(ui, server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM