【问题标题】:How to access secondary inputs with variable names in R Shiny?如何在 R Shiny 中使用变量名访问辅助输入?
【发布时间】:2021-04-14 08:24:39
【问题描述】:

我试图让用户输入一个数字输入,然后生成与第一个数字输入相等的输入框数量。然后我想找到对这些辅助数字输入的响应的总和。但是,我无法以全面的方式访问这些变量,因为它们的名称是使用数字变量创建的。现在当我运行它时,我得到这个错误: Warning: Error in get: object 'inp21' not found

谢谢

library(shiny)

ui <- fluidPage(
    
    # Application title
    titlePanel("Test"),
    
    sidebarLayout(
        sidebarPanel(
            numericInput("inp1",
                         "Enter num:",1)
        ),
 
        mainPanel(
            uiOutput("more_inp"),
            textOutput("num_inps")
        )
    )
)


server <- function(input, output) {
    
    counter <- reactiveValues(countervalue = 0)
    counter2 <- reactiveValues(counter2value = 0)
    
    output$more_inp <- renderUI({
        
        #Generates number of numeric inputs equal to original numeric input
        mylist <- lapply(1:input$inp1, function(i) {
            
            inp_identifier <- paste("inp2", i, sep="")
            inp_name<- paste("Input2",i,sep=" ")
            
            
            list(
                numericInput(inp_identifier,inp_name, 5)
            )
            
        })
        do.call(tagList, unlist(mylist, recursive = FALSE))
    })
    
    #Display number of secondary inputs
    
    #Count number of secondary inputs
    observeEvent(input$inp1, {
        counter$countervalue <- counter$countervalue + 1     
    })
    
    #Find sum of secondary inputs
    output$num_inps<-renderText(input$inp1)
    
            observeEvent(input$inp1,{
                for (i in 1:counter$countervalue) {
                    counter2$counter2value <- counter2$counter2value + get(paste("inp2", i, sep=""))
                    print(counter2$counter2value)
                }
            })
       
}

运行应用程序

shinyApp(ui = ui, server = server)

【问题讨论】:

  • 尝试用input[[paste("inp2", i, sep="")]]替换get(paste("inp2", i, sep=""))
  • 解释:如果它是预定义的,你会将它引用为input$inp21input[["inp21"]],而不是get("inp21")
  • @r2evans 谢谢!我试过了,现在它将 print(counter2$counter2value) 的值打印为 numeric(0)。你知道这里发生了什么吗?谢谢
  • @r2evans BTW,numeric(0) 指的是长度为 0 的数字向量。
  • 请不要通过破坏您的帖子为他人增加工作量。通过在 Stack Exchange 网络上发帖,您已在 CC BY-SA 4.0 license 下授予 Stack Exchange 分发该内容的不可撤销的权利(即无论您未来的选择如何)。根据 Stack Exchange 政策,帖子的非破坏版本是分发的版本。因此,任何破坏行为都将被撤销。如果您想了解更多关于删除帖子的信息,请参阅:How does deleting work?

标签: r loops user-interface input shiny


【解决方案1】:

除了 r2evans 的建议之外,还可以简单地“过滤”出无法找到输入字段的情况。似乎在创建其他输入字段之前调用了这个observeEvent。因此,当您尝试访问其中一个时,您会收到一个空向量 (numeric(0))。

  observeEvent(input$inp1,{
    for (i in 1:counter$countervalue) {
      if (isTruthy(input[[paste0("inp2", i)]])) {
        counter2$counter2value <- counter2$counter2value + input[[paste0("inp2", i)]]
        print(counter2$counter2value)
      }
    }
  })

【讨论】:

    【解决方案2】:

    在添加之前您没有检查是否存在。 observeEvent 块正在积极触发,因此即使 counter$countervalue 为 1,也没有其他输入字段存在,因此 input[[paste("inp2", i, sep="")]] 返回 NULL。任何加上 null 的都是 numeric(0)

    如何找到这个

      observeEvent(input$inp1,{
        browser()
        for (i in 1:counter$countervalue) {
          counter2$counter2value <- counter2$counter2value + get(paste("inp2", i, sep=""))
          print(counter2$counter2value)
        }
      })
    

    运行您的应用。当它点击调试器并显示Browse[2]&gt;,然后

    counter$countervalue
    # [1] 1
    counter2$counter2value
    # [1] 0
    i <- 1L
    get(paste("inp2", i, sep=""))
    # Error in get(paste("inp2", i, sep = "")) : object 'inp21' not found
    input[[ paste("inp2", i, sep="") ]]
    # NULL
    names(input)
    # [1] "inp1"
    

    快速检查可能是在 names(input) 中查找 paste(.) 名称。

    切线

    for (i in 1:n) 可以正常工作,只要您 100% 确定此处的 n 将始终为 1 或更大。如果极有可能是&lt;1,那么结果将相当不直观。

    也就是说,如果n 为0,那么我希望for 循环什么也不做。以向量为例,

    for (nm in c('a','b')) ...  # executes twice     GOOD
    for (nm in c()) ...         # does not execute   GOOD
    for (i in 1:2) ...          # executes twice     GOOD
    for (i in 1:0) ...          # executes twice     BAD
    

    原因是1:0 解析为反向序列,因此seq(1, 0) 和因此c(1L, 0L)

    如果您预计可能为零,则更安全的选择是seq_len

    seq_len(2)
    # [1] 1 2
    seq_len(0)
    # integer(0)
    

    seq(1, length.out=n) 等价。)

    如果你不能保证“只有正面”,那么一个更安全的选择,那么

    seq_len(max(0, n))
    

    (因为seq_len(-1) 是一个错误)。

    建议的解决方案

      observeEvent(input$inp1,{
        for (i in seq_len(counter$countervalue)) {    # or max(0, ...)
          nm <- paste("inp2", i, sep="")
          if (nm %in% names(input)) {
            counter2$counter2value <- counter2$counter2value + input[[nm]]
            print(counter2$counter2value)
          }
        }
      })
    

    【讨论】:

    • 太棒了。非常感谢。现在可以了。我在另一个按钮中添加了按下它后计算总和。这让事情变得更加顺利
    猜你喜欢
    • 2014-07-12
    • 1970-01-01
    • 2018-11-18
    • 1970-01-01
    • 2013-02-25
    • 2013-11-28
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多