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

如何将R Shiny动态生成的用户输入值存储到dataframe中

R Shiny动态输入转Dataframe实现方案

核心修改点

  • 将原未绑定变量的eventReactive赋值给响应式变量df
  • 基于当前输入组计数循环提取所有动态生成的输入值,拼接为结构化dataframe
  • 修正输出ID大小写不匹配问题:UI中定义的输出ID为Dataframe,服务端渲染逻辑需和该ID保持一致

完整修正后代码

library(shiny)

ui <- fluidPage(
 
  fluidRow(
    column(
      width = 6,
      uiOutput("selection_ui")
    ),
      
    column(
      width = 3,
      uiOutput("amount_ui")
    ),
    
    column(
      width = 3,
      uiOutput("year_ui")
    )
  ),
  
  fluidRow(
    column(
      width = 6,
      actionButton(inputId = "addEntry", 
                   label = "Add Entry")
    ),
    
    column(
      width = 6,
      actionButton(inputId = "deleteEntry",
                   label = "Delete Entry")
    )
  ),
  br(),
  
  fluidRow(
    column(
      width = 12,
      actionButton(inputId = "Go",
                   label = "Submit")
    )
  ),
  
  dataTableOutput("Dataframe")
)

server <- function(input, output){
  
  counter <- reactiveValues(value = 1)
  
  AllInputs <- reactive({
    x <- reactiveValuesToList(input)
  })
  
  observeEvent(input$addEntry, {
    counter$value <- counter$value + 1
  })
  
  observeEvent(input$deleteEntry, {
    req( counter$value >= 2 )
    counter$value <- counter$value - 1
  })
  
  selection <- reactive({
    n <- counter$value
    
    if(n > 0){
      isolate({
        lapply(seq_len(n), function(i){
          selectInput( inputId = paste0("select",i),
                       label = paste0(i, "-th selection:"),
                       choices = as.list(c("", "A", "B", "C")),
                       selected = AllInputs()[[paste0("select",i)]]
          )
        })
      })
    }
  })
  
  amount <- reactive({
    n <- counter$value
    
    if(n > 0){
      isolate({
        lapply(seq_len(n), function(i){
          numericInput(inputId = paste0("number",i),
                       label = paste0(i, "-th amount:"),
                       value = AllInputs()[[paste0("number",i)]])
        })
      })
    }
  })
  
  year <- reactive({
    n <- counter$value
    
    if(n > 0){
      isolate({
        lapply(seq_len(n), function(i){
          numericInput(inputId = paste0("year",i),
                       label = paste0(i, "-th year:"),
                       value = AllInputs()[[paste0("year",i)]])
        })
      })
    }
  })
  
  output$selection_ui <- renderUI({selection()})
  output$amount_ui <- renderUI({amount()})
  output$year_ui <- renderUI({year()})

  # 动态生成Dataframe逻辑
  df <- eventReactive(input$Go, {
    req(counter$value >= 1)
    # 循环提取每一组输入的值,拼成三列数据框
    data.frame(
      selection = sapply(seq_len(counter$value), function(i) input[[paste0("select", i)]]),
      amount = sapply(seq_len(counter$value), function(i) input[[paste0("number", i)]]),
      year = sapply(seq_len(counter$value), function(i) input[[paste0("year", i)]]),
      check.names = FALSE
    )
  })
  
  output$Dataframe <- renderDataTable(df())
}

shinyApp(ui = ui, server = server)

如果需要处理输入为空的场景,可以在提取输入值时补充空值默认逻辑,比如用input[[paste0("select", i)]] %||% NA替换直接取值的逻辑,即可避免空输入导致的报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:12:01