R闪亮传递对selectInput选择的反应


75

服务器端的一个闪亮的应用程序中(通过RStudio),我有一个反应式,可以通过解析a的内容来返回变量列表textInput。然后在selectInput和/或中使用变量列表updateSelectInput

我不能使它工作。有什么建议?

我做了两次尝试。第一种方法是outVar直接使用反应堆selectInput。第二种方法是使用反应性outVarupdateSelectInput。都不行。

服务器

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)
    })

})

用户界面

shinyUI(
  basicPage(
    uiOutput("inBody"),
    uiOutput("inVar")
  )
)

不久前,我在发亮的讨论中发布了相同的问题,但是它引起的兴趣不大,所以我再次道歉,https: //groups.google.com/forum/#!topic / shiny-讨论/ e0MgmMskfWo

编辑1

@Ramnath友好地发布了一个似乎有效的解决方案,他表示为Edit 2。但是该解决方案无法解决问题,因为该问题在我的问题textinputui侧面而不是server侧面。如果我将textinputRamnath的第二个编辑的内容移到server侧面,问题会再次出现,即:什么都没有显示,并且RStudio崩溃。我发现,包裹input$textas.character使问题消失。

编辑2

在进一步的讨论中,Ramnath向我展示了当服务器尝试outVar在其参数由返回之前应用动态函数时,就会出现问题textinput。解决的办法是先检查是否is.null(input$inBody)存在。

检查参数是否存在是构建闪亮应用程序的关键方面,那么为什么我没有想到呢?好吧,我做到了,但是我一定做错了!考虑到我在此问题上花费的时间,这是一次痛苦的经历。我在代码之后显示如何检查是否存在。

下面是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的支票更为直接。

最后,我想说明一些有关各种调试尝试的信息。

在我的调试任务中,我发现有一个选项可以在服务器端对“输出”的优先级进行“排序”,这是我尝试解决问题的方法,但由于该问题在其他地方而没有用。不过,仍然很有趣,并且目前似乎还不是很了解:

outputOptions(output, "textbox", priority = 1)
outputOptions(output, "variables", priority = 2)

在该任务中,我还尝试了 try

try(vars <- all.vars(parse(text = input$text)))

那已经很接近了,但是仍然没有解决。

我偶然发现的第一个解决方案是:

vars <- all.vars(parse(text = as.character(input$text)))

我想知道它为什么起作用会很有趣:是因为它使事情变慢了吗?是因为as.character“等待”input$text为非空吗?

无论情况如何,我都非常感谢拉姆纳特的努力,耐心和指导。


2
renderUI用于动态更改的输入元素。在您的情况下,textInput最好将UI放置在UI中,因为其中不涉及动态元素。
Ramnath

@ Ramnath,这是一个简化的示例:我的设置中确实包含动态元素:-)
PatrickT 2014年

在我问题的第一行,我写了 服务器端。如果阅读我的代码,您会发现它涵盖了所有常见情况。奇怪的是,需要as.characterserver一侧而不是一侧包装输入ui。您会认为是错误吗?还是您期望的功能?哦! 有人
拒绝投票

这不是错误。如果您input$inBody在进行all.vars呼叫之前先检查是否存在,它仍然可以工作。因此,这并不是as.character真正重要的事情。这是我要表达的要点
Ramnath

Answers:


87

您需要renderUI在服务器端使用动态UI。这是一个最小的示例。请注意,第二个下拉菜单是反应性的,可根据您在第一个菜单中选择的数据集进行调整。如果您以前处理过闪亮代码,则代码应该是不言自明的。

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

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。在此应用程序中,输入的文本公式用于使用变量列表动态填充下面的下拉菜单。

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())
    })
  }
))

谢谢拉姆纳特,我认为我的问题有所不同。我已经成功完成了您names()在另一个应用中的操作。但是在这里,我尝试传递outVar()selectInput(),在其中outVar()输出反应式列表。可能是的问题outVar(),但我不知道是什么,或者是事件序列中的时间安排问题。也许这也是一个愚蠢的错误。您在我的代码中看到错误吗?我是否需要明确names()有关get()?谢谢!
PatrickT 2014年

如果我写return(list("a","b"))在顶部,outVar()那么它将起作用。但是,如果我保留上面给出的代码并在控制台中查看,则str(outVar())返回的结果恰好是str(list("a","b"))返回值(从视觉上来说),因此我认为我的问题是时间问题。在outVar()当时还没有准备好selectInput()所需要的choices,可能是这个问题?
PatrickT 2014年

AFAIK,如果需要动态UI元素,则需要使用renderUIupdateSelectInput方法。这克服了您所指的时间问题。
Ramnath

谢谢拉姆纳特,我上面的代码有一个updateSelectInput方法,但是没有用。任何想法?谢谢!
PatrickT 2014年

我认为我遇到的问题与步骤顺序有关,我尝试进行设置,outputOptions(output, "inBody", 1)outputOptions(output, "inVar", 2)希望updateSelectInput有耐心等待outVar()准备就绪,但这没什么区别,因此问题可能出在其他地方。您可以用parse而不是已知列表作为示例吗?感谢您的尝试!
PatrickT 2014年

3

据我所知,问题是即使函数被赋予a作为值,input$inBody也不会检索a 。因此,该解决方案是包装在一个characterselectInputcharactervalue = "a+b+c"input$inBodyas.character

以下作品:

observe方法updateSelectInput

observe({
     input$inBody
     vars <- all.vars(parse(text=as.character(input$inBody)))
     vars <- as.list(vars)
     updateSelectInput(session = session, inputId = "inVar", choices = vars)
})

reactive方法selectInput

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解释了这个问题并提供了更好的解决方案,我将其作为对我的问题的修改。我将保留此答案作为记录。


1

服务器

### 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 ##

用户界面

uiOutput("carControls"),
  br(),
  textOutput("selectedText")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.