R блестящая передача, реагирующая на выбор selectInput

в блестящем приложении (от RStudio), на сервер сторона, у меня есть реактивный, который возвращает список переменных, разбирая содержимое textInput. Список переменных, используется в selectInput и/или updateSelectInput.

я не могу заставить его работать. Есть предложения?

я сделал две попытки. Первый подход заключается в использовании реакционноспособных outVar непосредственно в selectInput. Второй подход заключается в использовании реакционноспособных outVar на updateSelectInput. Ни завод.

сервер.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)
    })

})

пользовательский интерфейс.R

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

некоторое время назад я отправил тот же вопрос в shiny-discuss, но он вызвал мало интереса, поэтому я спрашиваю снова, с извинениями,https://groups.google.com/forum#!тема / блестящие-обсуждение/e0MgmMskfWo

изменить 1

@Ramnath любезно опубликовал решение, которое, похоже, работает, обозначено Изменить 2 по ним. Но это решение не решает проблему, потому что textinput на ui сторона вместо server сторона, как это в моей проблеме. Если я сдвину textinput второго редактирования Рамната в server сторона, проблема возникает снова, а именно: ничего не показывает и RStudio падает. Я нашел эту обертку!--20--> на as.character проблема исчезает.

Изменить 2

в дальнейшем обсуждении, Ramnath показал мне, что проблема возникает, когда сервер пытается применить динамическую функцию outVar прежде чем его аргументы будут возвращены textinput. Решение сначала проверить, является ли .

Проверка наличия аргументов является важным аспектом создания блестящего приложения, так почему же я об этом не подумал? Да, но я, должно быть, сделал что-то не так! Учитывая сколько времени я потратил на эту проблему, это горький опыт. Я покажу после кода, как проверьте существование.

Ниже приведен код 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)
}

оба, кажется, работают, но я буду делать это по-Рамнат с этого момента: возможно, несбалансированный кронштейн в моей конструкции ранее помешал мне сделать проверку работа? Проверка рамната более прямая.

наконец, я хотел бы отметить пару вещей о моих попытках отладки.

в моем отладочном поиске я обнаружил, что есть возможность "ранжировать" приоритет "выходов" на стороне сервера, который я исследовал в попытке решить мою проблему, но не работал, так как проблема была в другом месте. Тем не менее, это интересно знать и, кажется, не очень хорошо известно в это время:

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 быть не-null?

3 ответов


вам нужно использовать renderUI на стороне сервера для динамических UIs. Вот минимальный пример. Обратите внимание, что второе раскрывающееся меню является реактивным и настраивается на набор данных, выбранный в первом. Код должен быть понятным, если вы имели дело с 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

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

насколько я могу судить, проблема в том, что input$inBody не получить character хотя selectInput функция имеет значение character как значение, а именно value = "a+b+c". Поэтому решение заключается в том, чтобы обернуть input$inBody на as.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())
})

Edit: я отредактировал мой вопрос с объяснением, основанным на отзывы Ramnath по. Рамнат объяснил проблему и предоставил лучшее решение, которое я даю в качестве редактирования моего вопроса. Я сохраню этот ответ, но он не заслуживает голосов.


сервер.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")