You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R语言Shiny中重置eventReactive响应式值及解决报错?

Shiny应用重置与响应式值处理问题

我开发了一个使用plotly展示数据的shiny应用,数据通过actionButton加载。在完整应用中,存在大量依赖该加载数据的后续响应式观察者及其他响应式值,最终数据将从文件读取,我希望用户能够重置所有内容,完全回到初始状态。但我发现,除非将响应式值存储在reactiveValues()中,否则无法删除该响应式值或至少将其设为NULL。我更倾向于在观察者中使用req()而非if(!is.null()),并尽可能使用Dat()而非vals$dat的写法。


无法运行的代码

UI代码

library(shiny)
library(shinyjs)
library(plotly)

df <- data.frame(t=seq(as.POSIXct("2024-01-01 00:00:00", tz='UTC'),
                       as.POSIXct("2024-01-02 00:00:00", tz='UTC'), by="1 hour"),
                 V1=sample(1:50,25, replace=T))

ui <-shinyUI(fluidPage(
  shinyjs::useShinyjs(),
  fluidRow(
      actionButton("getdat", "Get my Data"),
      actionButton("reset", "Reset"),
      ),
   fluidRow(
      plotlyOutput("plot"),
   )))

Server代码

server<- function(input, output, session) {
    
  Dat<-eventReactive(input$getdat, {
    return(df)
  })
  
  # 加载数据后禁用按钮
  observeEvent(input$getdat,{
    shinyjs::disable("getdat")
    })
  
  output$plot <- renderPlotly({
    req(Dat())
    Dat() %>%  
      plot_ly() %>%
      add_trace(x= ~t, y = ~V1, type='scatter', mode='line', visible=TRUE) %>%
      layout(showlegend=FALSE)
  })
  
  observeEvent(input$reset,{
    Dat()<-NULL
    shinyjs::enable("getdat")
  })
  
}

shinyApp(ui,server)

可以正常运行的代码(使用reactiveValues)

server<- function(input, output, session) {
  
  vals<-reactiveValues(
    Dat=NULL
  )
   
  # 加载数据并禁用按钮
  observeEvent(input$getdat,{
    vals$Dat<-df
    shinyjs::disable("getdat")
    })
  
  output$plot <- renderPlotly({
    if(!is.null(vals$Dat)){
      vals$Dat %>% 
      plot_ly() %>%
      add_trace(x= ~t, y = ~V1, type='scatter', mode='line', visible=TRUE) %>%
      layout(showlegend=FALSE)
    }
  })
  
  observeEvent(input$reset,{
    vals$Dat<-NULL
    shinyjs::enable("getdat")
  })
  
}

shinyApp(ui,server)

补充说明与新问题

我采用了@Stéphane Laurent的解决方案,并加入了完整应用中的部分复杂逻辑。我不清楚如何正确更新响应式容器,也不理解eventReactive与observeEvent的区别。此前我参考相关问题的解答使用了eventReactive。

我知道可以将时间戳更新逻辑加入updateData()函数,并在eventReactive中加入input$t0作为触发事件,但由于处理的数据集非常大,我希望避免每次修改参数都重新计算所有内容。

新增代码(出现报错)

UI代码

ui <-shinyUI(fluidPage(
  shinyjs::useShinyjs(),
  fluidRow(
    actionButton("getdat", "Get my Data"),
    actionButton("reset", "Reset"),
    textInput("bin", HTML("Average bin"), value = "1", placeholder = NULL),
    textInput("t0", HTML("Starttime"), 
              value = '2018/03/28 09:54:27',placeholder = NULL)
  ),
  fluidRow(
    plotlyOutput("plot")
  )))

工具函数

updateData <- function(dat,bin) {
  dat<-as.data.frame(
    dat %>%
      group_by(t = round_date(t, unit=paste0(bin,' hours')))%>%
      summarize(V1 = median(V1))
  )
  return(dat)
}

updateStarttime <- function(dat,t0){
  timediff<-difftime(dat$t[1],as.POSIXct(t0, tz='UTC'), unit='secs')
  dat$t<-dat$t-seconds(timediff)
  return(dat)
}

Server代码

server<- function(input, output, session) {
  
  rawDat <- reactiveVal()
  timeformat <- reactiveVal()
  
  observe(
    timeformat(grepl('[0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}', input$t0))
  )
  
  # 加载数据后禁用按钮
  observeEvent(input$getdat,{
    rawDat(df)
    shinyjs::disable("getdat")
  })
  
  # 对原始数据进行后续转换
  Dat <- eventReactive(c(input$getdat,input$bin,input$reset), {
    req(rawDat())
    updateData(rawDat(),input$bin)
  })
  
  observeEvent(input$t0, {
    req(Dat(),timeformat())
    df<-updateStarttime(Dat(),input$t0)
    Dat(df)
  })
  
  output$plot <- renderPlotly({
    req(Dat())
    Dat() %>%  
      plot_ly() %>%
      add_trace(x= ~t, y = ~V1, type='scatter', mode='line', visible=TRUE) %>%
      layout(showlegend=FALSE)
  })
  
  observeEvent(input$reset,{
    rawDat(NULL)
    shinyjs::enable("getdat")
  })
  
}

shinyApp(ui,server)

报错信息

Warning: Error in Dat: unused argument (df)

内容的提问来源于stack exchange,提问作者Anke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:35:57