42

R のメッセージ vs 猫 vs 印刷 vs など、あまり深く理解していませんが、メッセージをキャプチャして光沢のあるアプリで表示することは可能でしょうか?

例: 次のアプリは、cat ステートメント (および print ステートメントも) をキャプチャできますが、message ステートメントはキャプチャできません。

runApp(shinyApp(
  ui = fluidPage(
    textOutput("test")
  ),
  server = function(input,output, session) {
    output$test <- renderPrint({
      cat("test cat")
      message("test message")
    })
  }
))

回答が得られなかったので、shiny-discuss Google グループからのクロス ポスト。

4

2 に答える 2

48

Yihui は私が を使用することを提案withCallingHandlersしました。私の問題は、一度に複数のメッセージを1つずつ出力する関数があり、素朴なアプローチを使用すると最後のメッセージしか出力されなかったため、必要なことを正確に実行する方法でその関数を使用する方法がよくわかりませんでした。これが私の最初の試みです(表示するメッセージが1つしかない場合に機能します):

foo <- function() {
  message("one")
  message("two")
}

runApp(shinyApp(
  ui = fluidPage(
    actionButton("btn","Click me"),
    textOutput("text")
  ),
  server = function(input,output, session) {
    observeEvent(input$btn, {
      withCallingHandlers(
        foo(),
        message = function(m) output$text <- renderPrint(m$message)
      )
    })
  }
))

two\n出力のみが取得されることに注意してください。したがって、私の最終的な解決策は、パッケージのhtml関数を使用することでしたshinyjs(免責事項: 私はそのパッケージを作成しました)。これにより、要素内の HTML を変更または追加できます。それは完全に機能しました - 両方のメッセージがリアルタイムで印刷されました.

foo <- function() {
  message("one")
  Sys.sleep(0.5)
  message("two")
}

runApp(shinyApp(
  ui = fluidPage(
    shinyjs::useShinyjs(),
    actionButton("btn","Click me"),
    textOutput("text")
  ),
  server = function(input,output, session) {
    observeEvent(input$btn, {
      withCallingHandlers({
        shinyjs::html("text", "")
        foo()
      },
        message = function(m) {
          shinyjs::html(id = "text", html = m$message, add = TRUE)
      })
    })
  }
))
于 2015-05-27T18:45:37.023 に答える
3

これはそれほどエレガントではないことはわかっていますが、capture.output;を使用して少し似た問題を回避しました。残念ながら、メッセージ出力sinkを同時にキャプチャすることはできません。元の順序では取得できませんが、少なくとも両方のストリームを抽出できます (ここでは HTML に変換されています)。

runApp(shinyApp(
  ui = fluidPage(
    uiOutput("test")
  ),
  server = function(input,output, session) {
    output$test <- renderUI({
      HTML(
      paste(capture.output(type = "message", expr = { 
        message(capture.output(type = "output", expr = {
          cat("test cat<br>")
          message("test message")
          cat("test cat2<br>")
          message("test message2")
        }))
      }), collapse="<br>")
  )})
 })
)

出力:

test message
test message2
test cat
test cat2

おそらく、ユーザーが両方をキャプチャしたいだけでなく、それらを分離したい場合、これは便利な回避策になります。(あなたのshinyjsパッケージはきれいに見えます、それを見る必要があります!)

于 2016-11-21T01:01:42.213 に答える