如何在 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$inp21
或input[["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]>
,然后
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 或更大。如果极有可能是<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() 传递变量名的问题