如何避免在Shiny R绘图中出现闪烁错误?

5

我发现这个代码是J.Cheng提供的freezeReactiveValue的例子。但是,在绘图显示之前,有时会瞬间显示错误而不是绘图(需要更改几次输入才能得到)。据我所知,问题在于短时间内X和Y(列)保留了先前数据集的值,并且与新数据集不匹配。例如,当我选择“压力”数据集时,我会在一秒钟后收到错误消息“Error in FUN: object 'speed' not found”。(但是,只有在之前选择了x = Speed和y = pressure的“车辆”数据集才会出现此情况。)显然,绘图试图在更新变量之前获取x变量,但我不知道如何防止这种情况发生。如果您有任何提示,请告诉我!!!谢谢!

library(shiny)
library(ggplot2)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("dataset", "Dataset", c("cars", "pressure", "mtcars")),
      selectInput("x", "x variable", character(0)),
      selectInput("y", "y variable", character(0))
    ),
    mainPanel(
      plotOutput("plot")
    )
  )
)

server <- function(input, output, session) {
  dataset <- reactive({
    get(input$dataset, "package:datasets")
  })

  observe({
    freezeReactiveValue(input, "x")
    freezeReactiveValue(input, "y")
    columns <- names(dataset())
    updateSelectInput(session, "x", choices = columns, selected =    columns[[1]])
    updateSelectInput(session, "y", choices = columns, selected = columns[[2]])
  })

  output$plot <- renderPlot({
    Sys.sleep(2)
    req(input$dataset,input$x,input$y)
    ggplot(dataset(), aes_string(input$x, input$y)) + geom_point()
  })
}

shinyApp(ui, server)

4
你可以在 req 中添加另一个检查来查看 x 和 y 是否在数据集中:data <- dataset(); req(input$dataset, input$x, input$y, all(c(input$x, input$y) %in% colnames(data))); ggplot(data, aes_string(input$x, input$y)) + geom_point() 我不使用 Shiny,所以不知道正确的方法... 在这种情况下,你也可以删除 Sys.sleep - rawr
谢谢@rawr,这对我有用,但我希望有一个更通用的解决方案,一种检查X和Y输入是否“新鲜”并在数据集输入更改后已更新的方法。原因是,我有一个真正的问题要解决,基于这个例子(其中的数据很难在此处重现)。在我的情况下,旧的x、y和新/新鲜的x、y输入之间的区别不像这种情况那么清晰,因此我不知道如何知道我在使用更新后的x/y值。谢谢! - JustLearning
1个回答

3

这是关于响应性优先级和与“选择失效”相关的一点内容。我认为要确保原子更新(同时更新数据和输入),您需要将数据更新和输入更改组合到同一个块中,否则会出现执行顺序不符合预期的依赖块(即响应链中存在多个路径)。

其中一种方法是将副作用用于所有操作,而不仅仅是分配$x$y。(我仍在寻找不需要这种副作用的解决方案……)(借鉴了@rawr的评论)

使用您的ui,请尝试以下操作:

server <- function(input, output, session) {
  dataset <- reactiveVal()

  observeEvent(input$dataset, {
    req(input$dataset)
    x <- get(input$dataset, "package:datasets")
    columns <- names(x)
    updateSelectInput(session, "x", choices = columns, selected = columns[[1L]])
    updateSelectInput(session, "y", choices = columns, selected = columns[[2L]])
    dataset(x)
  })

  output$plot <- renderPlot({
    req(dataset())
    columns <- names(dataset())
    req(all(c(input$x, input$y) %in% columns))
    ggplot(dataset(), aes_string(input$x, input$y)) + geom_point()
  })
}

我已经将对 'x' 和 'y' 的赋值放入同一个观察块中,并将数据重新分配。这样,您可以相对确保在更改 input$dataset 后立即更新 selectInput


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接