Ioana Neagoe Ioana Neagoe - 2 months ago 24
R Question

Add reactive values from click events to existing data frame and update plot

I'm new to using Shiny and having some problems with adding reactive values to an existing data frame.

I would like to plot a scatter plot with a regression line using some preexisting data and update it with user clicks. I found a helpful example, but I can't figure out how to store the reactive values in a data frame in order to update the regression line.

Here is what I tried. Thank you.

library(shiny)

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

server <- function(input, output) {

var1 <- c(3, 10, 15, 3, 4, 7, 1, 12, 8, 18, 20, 4, 4, 5, 10)
var2 <- c(4, 10, 12, 17, 15, 20, 14, 3, 4, 15, 12, 5, 5, 6, 2)
df <- cbind (var1, var2)

val <- reactiveValues(clickx = NULL, clicky = NULL, data = NULL)
observe({
input$plot_click
isolate({
val$clickx = c(val$clickx, input$plot_click$x)
val$clicky = c(val$clicky, input$plot_click$y)
})

# isolate({
# val$data = rbind(df, c(val$clickx, val$clicky))
#})

}) #adding clicks to list


output$plot1 <- renderPlot({
plot(val$data[,1], val$data[,2])
input$updateplot
isolate({
points(val$clickx, val$clicky)
})
if(input$refreshlinie)
abline(lm(val$data[,1]~ val$data[,2]))
})

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

}

shinyApp(ui, server)

Answer

The basic idea is to initialize the reactive values with the pre-existing data. Late add to the reactive values the new points added.

Bellow I put a simplified version of your code that update the points in the vla$data and correctly update the abline.

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

server <- function(input, output) {

  var1 <- c(3, 10, 15, 3, 4, 7, 1, 12, 8, 18, 20, 4, 4, 5, 10)
  var2 <- c(4, 10, 12, 17, 15, 20, 14, 3, 4, 15, 12, 5, 5, 6, 2)
  n <- length(var1)

  # initialize reactive values with existing data
  val <- reactiveValues( clickx = NULL, clicky = NULL, data = cbind (var1, var2))

  observe({
    input$plot_click
    isolate({
      # save new points added
      val$clickx = c(val$clickx, input$plot_click$x)
      val$clicky = c(val$clicky, input$plot_click$y)
      # add new points to data
      val$data <- rbind(val$data, cbind(input$plot_click$x, input$plot_click$y))
    })
  })


  output$plot1 <- renderPlot({
    input$updateplot
    plot(val$data[,1], val$data[,2])
    if(input$refreshlinie)
      # I changed the order of the variables to create the model.
      abline(lm(val$data[,2]~ val$data[,1]))
  })

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

}

shinyApp(ui, server)