本日はShiny
でプログラムを作る際に必要となるデバッギングについてです。
想定通り動かない場合に変数の中身をチェックしたりは必須ですが、ここでは
私のようなShiny
初心者でも使えるテクニックをピックアップして補足解説します。
本日のネタは以下のオフィシャルサイトをベースに最低限必要な情報を整理してまとめます。
今回使うサンプルプログラム
Shiny
のチュートリアルにあるオールドフェイスフルの間欠泉データを使います。
(参考までに、old faithful geyserはアメリカにある最初に指定された国立公園にある有名な間欠泉のことです。
90分程度に1回判を押したように大規模に噴水するので観光客に人気です)
以下が今回利用するプログラムですが、コメントなどは外してさっぱりさせています。
library(shiny) ui <- fluidPage( titlePanel("Hello Shiny!"), sidebarLayout( sidebarPanel( sliderInput(inputId = "bins", label = "Number of bins:", min = 1, max = 50, value = 30) ), mainPanel( plotOutput(outputId = "distPlot") ) ) ) server <- function(input, output) { output$distPlot <- renderPlot({ x <- faithful$waiting bins <- seq(min(x), max(x), length.out = input$bins + 1) hist(x, breaks = bins, col = "#75AADB", border = "white", xlab = "Waiting time to next eruption (in mins)", main = "Histogram of waiting times") }) } shinyApp(ui, server)
ブレークポイントの設定
最も基本的なテクニックと思いますが、R Studio
の標準エディターだけでしか動かず、他のエディターには対応していないのが残念ですね。
さて使い方はシンプルで、行番号の左端をクリックすると赤い丸印が出てきます。これでブレークポイントが設置できました。
この状態でプログラムを実行するとブレークポイントでプログラムが停止して以下の画面が現れます。
このときに画面右側のEnvironment
タブには以下のような変数情報が表示されます。
変数x
にx <- faithful$waiting
で情報を入れたところで停止しているので、
変数x
に入ったデータの値(value)を表示して止まっています。
このプログラムではまだ変数x
だけに情報を入れているのでこれしか表示していませんが、
その時点で登録された変数の情報はすべて確認することができます。
その後F10
を押すごとに1ステップ実行していきますので、変数の中身などが想定通り入っているかなどを
確認することができます。
ブレークポイントの注意点
- ブレークポイントは
server.R
にしか設定できません。ui.Rやglobal.Rなどに設定したブレークポイントは無視されます。 - ブレークポイントはそのポイントが実行されたときにストップするので、そのコードが実行されていることはわかるが、
ブレークポイントに到達しないと実行がストップしないので、”なぜこのコードが実行されないのか” がわからないという
問題点がある。 - R StudioのIDEでしか動かない。
browser()
もう一つの解決方法がプログラムにブレークポイントbrowser()
を記載する方法です。
基本的な使い方はブレークポイントと一緒で、プログラムを止めたい点にbrowser()
のコードを挿入するだけですので簡単です。
以下の画面が実行した時の結果ですが、そのときに変数の情報がEnvironment
タブに表示さており基本的に同じように使えます。
browser()
によるブレークポイントはプログラムの中に埋め込めるので以下のような特徴を備えています。
server.R
以外でも埋め込める- 条件付きでブレークポイントを発動させるなどの制御が可能となる。
以下ではセレクターが40以上になったときにブレークポイントが発動される例です。
プログラムを実行してスライダーを動かしてみてください。
CATによる変数の出力
もう一つ極めて原始的なテクニックもご紹介します。
上記のデバッギングはR Studio
の謹製ですが、簡単に確認する方法として
変数をログに出力させるという方法もあります。
ログ出力はcat
関数を使います。
cat(file=stderr(), "myValue= ", myValue , "\n")
のように使います。
スライダーを40以上にセットしたときに、input$bins
の値がログにプリントされます。
プログラムにこれを仕掛けておけばコードがポーズした時点での途中経過を確認しながら進めることができます。
CAT利用時の注意点
変数の動きを見るためにCATの中に表示する変数としてリアクティブ変数を使う場合プログラムの
動きが変になる可能性があるのでご注意ください。
背景として、リアクティブ変数はその中身が変化したときに自動的に反応するので、CATに含まれるリアクティブ変数により
想定していなかったタイミングで
リアクティブが働いて思わぬ部分(CAT周辺)のプログラムが実行されてしまう可能性があるためです。
くれぐれもCAT+リアクティブ変数の組み合わせは慎重にご利用ください。
グローバル変数に入れて後から確認する方法
Shiny
のグローバル変数はいくつかの方法があって影響の範囲を理解するのがややこしいのが欠点です。
ui.R
やserver.R
の中で設定した変数は、セッションを終了すると消えてしまいますが、その途中状況をスナップショットとして
残しておきたい場合などには変数の値をグローバル変数として放り込んでしまう方法があります。
具体的には、
test_outVar <<- outVar
のように、残したい変数を(<<-
)で変数に入れればセッションを終了しても値がEnvironment
に残ります。
プログラム終了後に値を確認したい場合などには使い道もあります。
Reactive Logパッケージを使ったリアクティブ動作のデバッグ
ここまでのテクニックは基本的に静的な変数の動きを確認するための手段を紹介してきました。
Shiny
のプログラムを作っていて問題になるのがリアクティブな動きが想定通り働かないといったケースではないでしょうか。
こんな時に頼もしいツールがreactlog
パッケージです。
使い方は簡単で、CRAN
からreactlog
パッケージをインストールしたら、プログラムの頭に以下の2行を加えるだけです。
options(shiny.reactlog = TRUE) library(reactlog)
ではold faithful
のプログラムに上記を追加して実行してみます。
プログラムはスライダーのインプット待ちで止まりますので、そのときに
Ctrl + F3`` (Mac: Cmd + F3)
を実行してください。以下のようなリアクティブログ画面が立ち上がります。
(画面が立ち上がらないときは何度か押してみると良いようです)
この状態はその時点でのリアクティブ変数の状態を示しています。画面の上部に何種類かの矢印が出ているので一番左の矢印を押すとプログラムの最初の状態になります。
その後は右矢印(next step)を押していけばどういった順番に情報のやりとりがなされているのか見ることができます。
残念ながら私はまだこのreactlog
を使いこなせていませんが、動きが変だと感じたときには使ってみると原因が特定できる可能性があります。
ただし、大きなプログラムになるとエレメントや矢印が複雑になるので扱いをうまくやる必要がありそうです。このあたりは、サーチ、フィルター、ズームなどいろいろな
機能が搭載されているようですので使いこなせれば強力なツールになると思います。
当面管理人を含むShiny
の初級者には、原始的ではありますが、これまでに紹介したテクニックで変数に情報がうまく格納されたかを一つ一つ見ていくのが結局近道のように思います。
最後に
今回はShiny
のチュートリアルをベースに管理人のレベルに合わせて必要な情報を整理してまとめてみました。
より詳細は以下のチュートリアルを参考にしてさらに深掘りしてください。