R闪亮(R Shiny):如何在按下actionButton时更新反应式数据框,而不创建新的反应式数据框?

41

我的应用程序允许用户使用fileInput上传csv文件,并将其存储为响应式对象df_data。然后我创建了一个numericInput,供用户输入要从数据框中删除的行号。但是,我遇到了一个关于evaluation nested too deeply: infinite recursion / options(expressions=)?的错误。

以下是我的ui.R代码。

shinyUI(fluidPage(
  titlePanel("amend data frame"),

  mainPanel(
    fileInput("file", "Upload file"),

    numericInput("Delete", "Delete row:", 1, step = 1),
    actionButton("Go", "Delete!"),

    tableOutput("df_data")
  )
))

以下是我的 server.R 代码。

shinyServer(function(input, output) {
  df_data <- reactive({
    read.csv(input$file$datapath)
  })

  df_data <- eventReactive(
    input$Go,
    df_data()[-input$Delete,]
  )

  output$df_data <- renderTable(df_data())
})

我通过将子集数据框分配给一个名为 df_data2 的新反应性数据框来解决了这个问题。但是,我希望让用户能够通过在删除行中输入值并按下Go按钮来不断删除不同的行。那么这种解决方案将不起作用,因为我将不得不分配df_data3、df_data4等等,而我无法预测用户将按Go按钮的次数。

我是一个新手用户,学习 shiny 已经有两周时间了,我已经搜索了一周的解决方案。是否有人可以帮助我?非常感谢!!

1个回答

80

下面是一个可运行的解决方案。我创建了一个reactiveValues来存储数据框。当选择文件时,数据框被填充。当删除按钮被按下时,相同的数据框将删除一行。该表始终输出该数据框对象所持有的内容。我希望这段代码可以成为一个很好的学习材料。

runApp(shinyApp(
ui=(fluidPage(
  titlePanel("amend data frame"),

  mainPanel(
    fileInput("file", "Upload file"),

    numericInput("Delete", "Delete row:", 1, step = 1),
    actionButton("Go", "Delete!"),

    tableOutput("df_data_out")
  )
)),
server = (function(input, output) {
  values <- reactiveValues(df_data = NULL)

  observeEvent(input$file, {
    values$df_data <- read.csv(input$file$datapath)
  })

  observeEvent(input$Go, {
    temp <- values$df_data[-input$Delete, ]
    values$df_data <- temp

  })

  output$df_data_out <- renderTable(values$df_data)
})))

谢谢!这很有效!我想进一步问一下为什么需要使用observeEvent()而不是observe()。两者之间有什么区别?谢谢! - Lawrence Lee
6
你可以使用常规的 observe。主要区别在于 observeEvent 作为参数接收要监听的反应式,因此表达式中的任何其他反应式值默认情况下都是隔离的。此外,当反应式为NULL时,它不会触发,这通常是处理输入时所需的(否则通常会得到 observe 中的第一行是 if(is.null(input$xxx)) return())。 - DeanAttali
我很高兴你这么认为 :) - DeanAttali
1
因此,没有仅使用反应式表达式的解决方案。您需要使用reactiveValues。 - MySchizoBuddy
这种解决方案仍然是建议的方法吗?问题和答案已经几年了,因此确认一下这是否仍然是建议的解决方案会很好。 - Jochem
1
@Jochem,我不知道这是否是最好的方法,但这个解决方案仍然有效。(2020年8月) - Luis

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