I want to create an interactive plot in R Shiny.
Based on some inputs a reactive data frame is created and visualised in a simple scatter plot. Now I want to allow users to select observations in the plot (by clicking the respective points). Everytime a point in the plot is clicked I want to update the column named "selected" in the data frame.
I tried the following code:
library(shiny)
library(ggplot2)
library(tidyverse)
ui <- fluidPage(
# Input
numericInput("N", label = "Number of participants", min = 1, max = 10, value = 10),
# Outputs
plotOutput(outputId="plot", click = "plot_click"),
textOutput(outputId = "info"),
tableOutput(outputId ="tab")
)
server <- function(input, output, session) {
# create data frame with random age for the selected number of persons
data <- reactive({
tibble(ID = 1:input$N, age = sample(1:100,input$N), selected = "no")
})
data <- reactive({
data() %>% mutate(selected =
if_else(ID == round(input$plot_click$x) & age == round(input$plot_click$y),"yes",selected))
})
output$tab <- renderTable({
data()
})
output$plot <- renderPlot({
ggplot(data(), aes(x = ID, y = age, color = selected)) + geom_point(size = 5)
})
output$info <- renderText({
if(is.numeric(input$plot_click$x)){
print(paste("x =",round(input$plot_click$x), "y =", round(input$plot_click$y)))
}
})
}
shinyApp(ui = ui, server = server)
However, with this code I get an error message:
Error in : evaluation nested too deeply: infinite recursion / options(expressions=)?
I also tried to create a new data frame instead of updating the old one with the following slightly adjusted code:
library(shiny)
library(ggplot2)
library(tidyverse)
ui <- fluidPage(
numericInput("N", label = "Number of participants", min = 1, max = 10, value = 10),
plotOutput(outputId="plot", click = "plot_click"),
textOutput(outputId = "info"),
tableOutput(outputId ="tab"),
tableOutput(outputId ="tab2")
)
server <- function(input, output, session) {
# create data frame with random age for the selected number of persons
data <- reactive({
tibble(ID = 1:input$N, age = sample(1:100,input$N), selected = "no")
})
data2 <- eventReactive(input$plot_click,{
data() %>% mutate(selected = if_else(ID == round(input$plot_click$x) & age == round(input$plot_click$y),"yes",selected))
})
output$tab <- renderTable({
data()
})
output$tab2 <- renderTable({
data2()
})
output$plot <- renderPlot({
ggplot(data(), aes(x = ID, y = age, color = selected)) + geom_point(size = 5)
})
output$info <- renderText({
if(is.numeric(input$plot_click$x)){
print(paste("x =",round(input$plot_click$x), "y =", round(input$plot_click$y)))
}
})
}
shinyApp(ui = ui, server = server)
I don't get an error message in this case and after clicking a point in the plot "data2" is created. However, the table of data2 is only visible for a very short moment and then disappears again.
I just started to work with R Shiny and still struggle a bit to understand the logic behind its reactivity. So I'll appreciate it a lot if someone could give me a hint here.
Thanks