Rのメッセージvs猫vs印刷vsなどについてはあまり理解していませんが、メッセージをキャプチャして、光沢のあるアプリで表示することは可能でしょうか。
例:次のアプリはcatステートメント(およびprintステートメントも)をキャプチャできますが、メッセージステートメントはキャプチャできません
runApp(shinyApp(
ui = fluidPage(
textOutput("test")
),
server = function(input,output, session) {
output$test <- renderPrint({
cat("test cat")
message("test message")
})
}
))
Yihuiは私がwithCallingHandlers
を使用することを提案しました。私の問題は、一度に複数のメッセージを出力する機能があり、単純なアプローチを使用すると最後のメッセージしか出力されないということだったので、必要な機能を正確に実行する方法がわかりませんでした。これが私の最初の試みです(表示するメッセージが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)
})
})
}
))
これはそれほどエレガントではないことはわかっていますが、capture.output
を使用して少し似た問題を回避しました。残念ながら、sink
はmessage sとoutputの同時キャプチャを許可しません。それらを元の順序で取得することはできませんが、少なくとも両方のストリームを抽出できます(ここでは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
パッケージはきれいに見えます、それを見てみる必要があります!)