如何在 R Shiny 中使用变量名访问辅助输入?

Posted

技术标签:

【中文标题】如何在 R Shiny 中使用变量名访问辅助输入?【英文标题】:How to access secondary inputs with variable names in 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? 【参考方案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)
      
    
  )

【讨论】:

太棒了。非常感谢。现在可以了。我在另一个按钮中添加了按下它后计算总和。这让事情变得更加顺利

以上是关于如何在 R Shiny 中使用变量名访问辅助输入?的主要内容,如果未能解决你的问题,请参考以下文章

运行 R Shiny 应用程序时如何在数据表函数中编辑列名?

在 R/Shiny 中通过 selectInput() 传递变量名的问题

R Shiny:如何在嵌套模块之间传递反应变量

Selectizeinput 输入互斥 R Shiny

在 Shiny 中使用部分 textInput 作为 R 中的变量

根据用户的输入创建列联表 - R Shiny