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

Shiny野外数据记录应用单元格编辑报错:invalid (NULL) left side of assignment

野外数据记录Shiny应用表格编辑问题解决

问题描述

开发了一款用于野外数据记录的Shiny应用,功能包括:

  • 观测人员通过selectInput或radioGroupButtons录入物种名称(sp)、性别(sexe)、体型(size,限3个选项)
  • 点击「Update Table」按钮将单行数据追加到响应式表格
  • 表格支持单元格编辑以修正录入错误

遇到的问题:

  1. 编辑表格后新增数据,之前的编辑内容会消失
  2. 添加observeEvent尝试修改响应式dataframe时触发错误:Error in <-: invalid (NULL) left side of assignment,仅修改为原值时不报错,修改为新值则报错

原应用代码

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "sp", label = "sp", choices = c("espece1", "espece2")),
      radioGroupButtons(inputId = "sexe", label = "sexe", choices = c("M", "F"), status = "custom-class"),
      radioGroupButtons(inputId = "size", label = "size", choices = c("30", "20", "10"), status = "custom-class"),
      actionButton("update", "Update Table")
    ),
    mainPanel(
      dataTableOutput("table1")
    )
  )
)

server <- function(input, output, session) {
  mydata <- reactiveVal(data.frame(sp = character(),
                                  sexe = character(),
                                  size = character(),
                                  stringsAsFactors = FALSE))
  
  observeEvent(input$update, {
    to_add <- data.frame(sp = input$sp,
                         sexe = input$sexe,
                         size = input$size)
    mydata(rbind(mydata(), to_add))
  })
  
  output$table1 <- DT::renderDataTable({
    datatable(mydata(), editable = "cell",
              options = list(pageLength = 50,
                             paging = FALSE))
  })
 
observeEvent(input$table1_cell_edit, {
    info <- input$table1_cell_edit
    row <- info$row
    col <- info$col
    value <- info$value
 
    mydata()[row,col] <- value
  })

}

shinyApp(ui, server)

已尝试的解决方案

  • 给info$row和info$col加1,仍报错
  • 使用mydata()[row,col] <<- isolate(DT::coerceValue(value, mydata()[row,col])),仍报错
  • 将响应式dataframe改为非响应式,触发错误:Error in <-: object of type 'closure' is not subsettable

解决方案

错误核心原因:

  1. mydata()是获取响应式变量值的函数,直接修改其返回的临时对象无法更新响应式变量,必须先提取当前数据,修改后重新赋值给mydata()
  2. DT的table1_cell_edit事件中,col是从0开始的索引,而R数据框的列索引从1开始,需要转换为col + 1
  3. 需确保修改后的数据类型与原列一致,可使用DT::coerceValue自动转换

修正后的observeEvent逻辑:

observeEvent(input$table1_cell_edit, {
  info <- input$table1_cell_edit
  # 转换DT的0起始索引为R的1起始索引
  row <- info$row + 1
  col <- info$col + 1
  value <- info$value
  
  # 提取当前响应式数据并修改
  current_data <- mydata()
  current_data[row, col] <- DT::coerceValue(value, current_data[row, col])
  # 更新响应式变量
  mydata(current_data)
})

修正后完整代码

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "sp", label = "sp", choices = c("espece1", "espece2")),
      radioGroupButtons(inputId = "sexe", label = "sexe", choices = c("M", "F"), status = "custom-class"),
      radioGroupButtons(inputId = "size", label = "size", choices = c("30", "20", "10"), status = "custom-class"),
      actionButton("update", "Update Table")
    ),
    mainPanel(
      dataTableOutput("table1")
    )
  )
)

server <- function(input, output, session) {
  mydata <- reactiveVal(data.frame(sp = character(),
                                  sexe = character(),
                                  size = character(),
                                  stringsAsFactors = FALSE))
  
  observeEvent(input$update, {
    to_add <- data.frame(sp = input$sp,
                         sexe = input$sexe,
                         size = input$size)
    mydata(rbind(mydata(), to_add))
  })
  
  output$table1 <- DT::renderDataTable({
    datatable(mydata(), editable = "cell",
              options = list(pageLength = 50,
                             paging = FALSE))
  })
 
observeEvent(input$table1_cell_edit, {
  info <- input$table1_cell_edit
  row <- info$row + 1
  col <- info$col + 1
  value <- info$value
  
  current_data <- mydata()
  current_data[row, col] <- DT::coerceValue(value, current_data[row, col])
  mydata(current_data)
})

}

shinyApp(ui, server)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 13:45:35