将行号列添加到 Shiny 中的反应式数据框

Add row number column to a reactive data frame in Shiny

我正在尝试将行索引列添加到根据用户输入即时创建的反应式数据框中。我可以使用 tibble::rowid_to_column 函数在 Shiny 之外执行此操作,但无法在下面的 Shiny 应用程序(第 44 行)中使用它。有人可以提供有关如何使其工作的指导吗?另外,当我从数据框中删除一行时,我们如何才能使 rowid 数字再次连续?谢谢

library(shiny)
library(DT)
library(tidyverse)


input_data <- data.frame(
  # rowid = double(),
  input1 = character(),
  input2 = double(),
  stringsAsFactors = FALSE)

ui <- fluidPage(
  
  titlePanel("Title"),
  
  sidebarLayout(
    sidebarPanel(
      selectInput("input1",
                  "Input 1",
                  choices = c("Value 1", "Value 2", "Value 3")),
      numericInput("input2",
                   "Input 2",
                   value = 100),
      actionButton("add_btn",
                   "Add Row"),
      actionButton("delete_btn", 
                   "Delete Row"),
      actionButton("reset_btn", 
                   "Reset"),
      position = "left"
    ),
    
    mainPanel(
      DT::dataTableOutput("input_table")
    )
  )
)

server <- function(input, output) {
  input_table <- reactiveVal(input_data)
  observeEvent(input$add_btn, {
    t = rbind(input_table(), data.frame(col1 = input$input1, col2 = input$input2)) 
    # %>%
    #   cbind(tibble::rowid_to_column("rowid"))
    input_table(t)
  })
  
  observeEvent(input$delete_btn, {
    t = input_table()
    print(input$input_table_rows_selected)
    if (!is.null(input$input_table_rows_selected)) {
      t <- t[-input$input_table_rows_selected,]
    }
    input_table(t)
  })
  
  observeEvent(input$reset_btn, {
    input_table(input_data)
  })
  
  output$input_table <- DT::renderDataTable({
    datatable(input_table())
  })
}

shinyApp(ui = ui, server = server)

rowid_to_column() 添加 tibble 的行名称并将它们作为列添加到数据框中。这对您不起作用:一旦您在列 rowid 中添加了行名,您就不能再次添加该列。此外,函数 returns 添加了新列的整个 tibble,因此 cbind()rowid_to_column() 的输出输出到 tibble 是没有意义的。

我建议对您的代码进行以下更改:

用rowid列定义初始Table:

input_data <- tibble(
  rowid = integer(),
  input1 = character(),
  input2 = double()
)

在第一个观察者中,将代码更改为:

observeEvent(input$add_btn, {
    new_row <- tibble(rowid = nrow(input_table()) + 1,
                      input1 = input$input1,
                      input2 = input$input2)
    t = bind_rows(input_table(), new_row)
    input_table(t)
  })

这将创建一个具有适当 rowid 的新行,然后将其添加到 table。

为了在删除行后获得预期的 rowid,您只需在每次删除行时重新定义 rowid:

observeEvent(input$delete_btn, {
  t <- input_table()
  print(input$input_table_rows_selected)
  if (!is.null(input$input_table_rows_selected)) {
    t <- t[-input$input_table_rows_selected, ]
    # reset the rowids only, when there is at least one row left
    if (nrow(t) > 0) {
      t$rowid <- 1:nrow(t)
    }
  }
  input_table(t)
})

并且在呈现输出 table 时,您必须抑制行名称:

output$input_table <- DT::renderDataTable({
  datatable(input_table(), rownames = FALSE)
})