首页 > 解决方案 > 在 R Shiny 中绘图后如何保留曲线?

问题描述

我正在构建一个闪亮的应用程序,用户可以在其中向绘图添加不同的曲线,但我无法使绘图保留已添加的曲线。我怎样才能做到这一点?

在下面的简化可重现代码中,共有 8 种曲线可能性,基于 3 个单选按钮选择,每个单选按钮有 2 个选项。我想将它们保留为单选按钮而不使用复选框,因为在我正在开发的真实应用程序中,将有大约 300 种组合,这些组合太混乱而无法与复选框一起使用。请看下面的代码:

library(shiny)
library(plotly)
library(dplyr)

data111 <-data.frame("x"=1:10, "y"=c(99,98,97,96,95,94,93,92,91,90))
data112 <-data.frame("x"=5:14, "y"=c(79,78,77,76,75,74,73,72,71,70))
data121 <-data.frame("x"=9:18, "y"=c(59,58,57,56,55,54,53,52,51,50))
data122 <-data.frame("x"=3:12, "y"=c(49,48,47,46,45,44,43,42,41,40))
data211 <-data.frame("x"=7:16, "y"=c(29,28,27,26,25,24,23,22,21,20))
data212 <-data.frame("x"=11:20, "y"=c(19,18,17,16,15,14,13,12,11,10))
data221 <-data.frame("x"=2:11, "y"=c(95,94,93,92,91,90,89,88,87,86))
data222 <-data.frame("x"=1:10, "y"=c(45,44,43,42,41,40,39,38,37,36))

ui <- fluidPage(
titlePanel("Curve selection"),
sidebarLayout(
  sidebarPanel(

     radioButtons(inputId = "option",
                 label="Choose the option",
                 choices=c("option1"=1,
                           "option2"=2),
                 selected = 1),

     radioButtons(inputId = "type",
                  label="Choose the type",
                  choices=c("type1"=1,
                            "type2"=2),
                  selected = 1),

     radioButtons(inputId = "group",
                  label="Choose the group",
                  choices=c("group1"=1,
                            "group2"=2),
                  selected = 1),

     actionButton("add","Add curve to the plot")
  ),

  mainPanel(
    plotlyOutput("plot")
  )
  )
)

server <- function(input, output) {

data <- eventReactive(input$add,{
 get(paste0("data",input$option,input$type, input$group))

})

output$plot <- renderPlotly({

 data <- data()

 p <-plot_ly(type = "scatter", mode="lines")
 p<-add_data(p, data) %>% add_trace(p, x= ~x, y = ~y)
 p

})
}

shinyApp(ui = ui, server = server)

我希望用户可以在单选按钮选择中选择选项、类型和组,然后添加曲线。之后,重新选择选项、类型和组,并将新曲线添加到图中已经存在的曲线中。用户应该能够多次执行此操作。你知道这是如何实现的吗?

谢谢!

标签: rshinyr-plotly

解决方案


您将必须使用一个reactiveValues对象,在其中保存已添加的跟踪。

然后您可以使用add_tracefor 循环,例如:

我将您更改eventReactiveobserveEvent,它将新数据附加到reactiveValues列表中。

为了防止两次绘制同一个对象,我创建了一个 reactiveValuesusedData对象,它将保存绘图图例名称。如果名称已在手边,则不会将任何内容添加到情节中。

server <- function(input, output) {

  d <- reactiveValues(a=NULL, name=NULL)
  usedData <- reactiveValues(d = NULL)

  data <- observeEvent(input$add,{
    src = paste0("data",input$option,input$type, input$group)
    var <- get(src)

    if (src %in% usedData$d) {
      print("Data is already plotted")
      req(F)
    }

    if (is.null(d$a)) {
      d$a <- list(var)
      d$name = list(src)
      usedData$d <- src
    } else {
      d$a <- append(d$a, list(var))
      d$name = append(d$name, list(src))
      usedData$d <- append(usedData$d, src)
    }
  })

  output$plot <- renderPlotly({
    req(d$a)
    data <- d$a
    names = d$name

    p <- plot_ly(data = data[[1]], type = "scatter", mode="lines")

    if (length(data) == 1) {
      p <- add_trace(p, x= ~x, y = ~y, name = names)
    } else {  
      for (i in 1:length(data)) {
        d <- data[[i]]
        p <- add_trace(p, data = d, x= ~x, y = ~y, type = "scatter", mode="lines", name = names[[i]])
      }
    }
    p
  })
}

推荐阅读