Rshiny传递反应selectInputselect
在一个shiny的应用程序(通过RStudio),在服务器端,我有一个反应,通过parsingtextInput
的内容返回一个variables列表。 然后在selectInput
和/或updateSelectInput
使用variables列表。
我无法做到这一点。 有什么build议么?
我做了两次尝试。 第一种方法是将react nativeoutVar
直接用于selectInput
。 第二种方法是使用updateSelectInput
的react nativeoutVar
。 两者都行不通。
server.R
shinyServer( function(input, output, session) { outVar <- reactive({ vars <- all.vars(parse(text=input$inBody)) vars <- as.list(vars) return(vars) }) output$inBody <- renderUI({ textInput(inputId = "inBody", label = h4("Enter a function:"), value = "a+b+c") }) output$inVar <- renderUI({ ## works but the choices are non-reactive selectInput(inputId = "inVar", label = h4("Select variables:"), choices = list("a","b")) }) observe({ ## doesn't work choices <- outVar() updateSelectInput(session = session, inputId = "inVar", choices = choices) }) })
ui.R
shinyUI( basicPage( uiOutput("inBody"), uiOutput("inVar") ) )
不久之前,我在shiny的讨论中发表了同样的问题,但这并没有引起什么兴趣,所以我再次问道, https: //groups.google.com/forum/#! topic/shiny-讨论/ e0MgmMskfWo
编辑1
@Ramnath慷慨地发布了一个似乎可行的解决scheme,由他编辑2 。 但是这个解决scheme没有解决这个问题,因为textinput
是在ui
端,而不是在server
端,因为它是在我的问题。 如果我将Ramnath的第二个编辑的文本input移动到server
端,问题再次出现,即:没有任何显示和RStudio崩溃。 我发现在as.character
中包装input$text
会使问题消失。
编辑2
在进一步的讨论中,Ramnath告诉我,当服务器在textinput
返回参数之前尝试使用outVar
dynamic函数时,会出现问题。 解决方法是首先检查是否存在is.null(input$inBody)
。
检查参数的存在是构build一个有光泽的应用程序的一个关键方面 ,所以为什么我没有想到呢? 那么,我做了,但我一定做错了! 考虑到我花在这个问题上的时间,这是一个痛苦的经历。 我在代码后显示如何检查存在。
下面是Ramnath的代码, textinput
移到了server
端。 它使RStudio崩溃,所以不要在家里尝试。 (我用他的符号)
library(shiny) runApp(list( ui = bootstrapPage( uiOutput('textbox'), ## moving Ramnath's textinput to the server side uiOutput('variables') ), server = function(input, output){ outVar <- reactive({ vars <- all.vars(parse(text = input$text)) ## existence check needed here to prevent a crash vars <- as.list(vars) return(vars) }) output$textbox = renderUI({ textInput("text", "Enter Formula", "a=b+c") }) output$variables = renderUI({ selectInput('variables2', 'Variables', outVar()) }) } ))
我通常检查存在的方式是这样的:
if (is.null(input$text) || is.na(input$text)){ return() } else { vars <- all.vars(parse(text = input$text)) return(vars) }
Ramnath的代码更短:
if (!is.null(mytext)){ mytext = input$text vars <- all.vars(parse(text = mytext)) return(vars) }
两者似乎都有效,但从现在开始我会这样做Ramnath的方式:也许我的构造中的一个不平衡的支架早已阻止我做检查工作? Ramnath的支票更直接。
最后,我想说明几个关于我的各种尝试debugging的事情。
在我的debugging任务中,我发现有一个选项可以在服务器端“排列”“输出”的优先级,我试图解决这个问题,但由于问题在其他地方,所以没有工作。 尽pipe如此,知道这件事很有意思,现在看起来并不是很有名:
outputOptions(output, "textbox", priority = 1) outputOptions(output, "variables", priority = 2)
在这个追求中,我也尝试过 :
try(vars <- all.vars(parse(text = input$text)))
这是非常接近,但仍然没有解决它。
我偶然发现的第一个解决scheme是:
vars <- all.vars(parse(text = as.character(input$text)))
我想知道它为什么起作用会很有趣:是因为它减慢了足够的速度? 这是因为as.character
“等待” input$text
是非空的吗?
无论如何,我非常感谢拉姆纳特的努力,耐心和指导。
您需要在服务器端使用dynamicUI的renderUI
。 这是一个最小的例子。 请注意,第二个下拉菜单是被动的,并根据您在第一个select的数据集进行调整。 代码应该是不言自明的,如果你之前已经处理了shiny。
runApp(list( ui = bootstrapPage( selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')), uiOutput('columns') ), server = function(input, output){ output$columns = renderUI({ mydata = get(input$dataset) selectInput('columns2', 'Columns', names(mydata)) }) } ))
编辑。 使用updateSelectInput
另一个解决scheme
runApp(list( ui = bootstrapPage( selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')), selectInput('columns', 'Columns', "") ), server = function(input, output, session){ outVar = reactive({ mydata = get(input$dataset) names(mydata) }) observe({ updateSelectInput(session, "columns", choices = outVar() )}) } ))
EDIT2:使用parse
修改示例。 在这个应用程序中,input的文本公式用于dynamic填充下面的variables列表下拉菜单。
library(shiny) runApp(list( ui = bootstrapPage( textInput("text", "Enter Formula", "a=b+c"), uiOutput('variables') ), server = function(input, output){ outVar <- reactive({ vars <- all.vars(parse(text = input$text)) vars <- as.list(vars) return(vars) }) output$variables = renderUI({ selectInput('variables2', 'Variables', outVar()) }) } ))
据我所知,问题是即使selectInput
函数被赋予一个character
作为值,即input$inBody
不会检索一个character
,即value = "a+b+c"
。 因此,解决scheme是将input$inBody
as.character
以下工作:
使用updateSelectInput
的observe
方法:
observe({ input$inBody vars <- all.vars(parse(text=as.character(input$inBody))) vars <- as.list(vars) updateSelectInput(session = session, inputId = "inVar", choices = vars) })
使用selectInput
的reactive
方法:
outVar <- reactive({ vars <- all.vars(parse(text=as.character(input$inBody))) vars <- as.list(vars) return(vars) }) output$inVar2 <- renderUI({ selectInput(inputId = "inVar2", label = h4("Select:"), choices = outVar()) })
编辑:我已经编辑我的问题,根据Ramnath的反馈解释。 拉姆纳特已经解释了这个问题,提供了一个更好的解决scheme,我把这个问题作为编辑。 我会保留这个答案,但不值得投票。
server.R
### This will create the dynamic dropdown list ### output$carControls <- renderUI({ selectInput("cars", "Choose cars", rownames(mtcars)) }) ## End dynamic drop down list ### ## Display selected results ## txt <- reactive({ input$cars }) output$selectedText <- renderText({ paste("you selected: ", txt() ,sep="") }) ## End Display selected results ##
ui.R
uiOutput("carControls"), br(), textOutput("selectedText")