1. ホーム
  2. r

[解決済み] selectInputの選択肢に反応的に渡すRの輝き

2023-05-12 14:41:53

質問

RStudioによる)シャイニーアプリで、(RStudioの) サーバー の内容をパースして変数のリストを返すリアクティブがあります。 textInput . この変数のリストは selectInput および/または updateSelectInput .

うまくいきません。何か提案があれば教えてください。

私は2つの試みをしてみました。最初のアプローチは、リアクティブな outVar の中に直接 selectInput . 2 番目の方法は、リアクティブな outVarupdateSelectInput . どちらも動作しません。

サーバ.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-discussに同じ質問を投稿しましたが、ほとんど関心を持たれなかったので、申し訳ありませんが、再度質問させていただきます。 https://groups.google.com/forum/#!topic/shiny-discuss/e0MgmMskfWo

編集1

Ramnath が親切にも、うまくいくように見える解決策を投稿してくれました。 編集 2 という解決策を投稿してくれました。しかし、その解決策は問題を解決するものではありません。 textinputui 側ではなく server 側ではなく、私の問題のように もし私が textinput に移動させると、Ramnathの2番目の編集は 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のチェックはより直接的です。

最後に、私のさまざまなデバッグの試みについて、2、3のことを書き留めておきたいと思います。

デバッグの探求において、サーバー側で "output" の優先度をランク付けするオプションがあることを発見し、私の問題を解決しようとして調査しましたが、問題は他の場所にあったのでうまくいきませんでした。それでも、知ることは興味深いことで、現時点ではあまり知られていないようです。

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になるのを待つのですか?

何はともあれ、Ramnathの努力、忍耐、指導に非常に感謝しています。

どのように解決するのですか?

この場合 renderUI をサーバ側で使用する必要があります。ここに最小限の例があります。2番目のドロップダウンメニューは反応型で、最初のメニューで選択したデータセットに適応することに注意してください。もしあなたが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))
    })
  }
))

EDIT. を使用した別の解決策 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())
    })
  }
))