shiny + HTML
- Shiny アプリの UI を、R のコードではなく手書きの HTML(www/index.html)で作る
- フォーム部品(テキスト、ファイル、チェックボックス、ラジオボタン)と Shiny の連携
- jQuery との連携(フォーム部品の色付け)
- networkD3 パッケージによるネットワークグラフの描画
前準備
前準備として、shiny パッケージをインストールしておくこと。
R システムで次のように操作する。
install.packages("shiny")
Shiny を使ってみる
Shiny アプリは、通常は R のコード(ui.R)で UI を定義するが、 アプリのディレクトリに www/index.html を置くと、手書きの HTML を UI として使うことができる。 HTML 側では、class 属性 shiny-html-output を持つ要素の id と、 server.R の output$〜 の名前を一致させることで、両者が結び付く。
- /tmp/server.R のサンプル
renderPrint と renderTable を使ってみる。
library(data.table) library(shiny) shinyServer(function(input, output) { output$summary <- renderPrint({ paste("n =", input$n) }) output$table <- renderTable({ head( data.table(iris), input$n ) }) }) - /tmp/www/index.html のサンプル
現在の HTML5 の書式で書く。shared/ 以下のファイル(shiny.css, jquery.min.js, shiny.min.js)は shiny パッケージが自動的に提供するので、用意する必要はない。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" type="text/css" href="shared/shiny.css"/> <script src="shared/jquery.min.js" type="text/javascript"></script> <script src="shared/shiny.min.js" type="text/javascript"></script> <title>HTML UI Sample</title> </head> <body> <h1>HTML UI</h1> <p> <input type="number" name="n" value="10" min="1" max="150" /> </p> <div id="summary" class="shiny-html-output"></div> <div id="table" class="shiny-html-output"></div> </body> </html> - 実行してみる
R システムで次のように操作する。
library(shiny) runApp("/tmp/") - Web ブラウザで表示してみる
runApp の実行時に「Listening on http://127.0.0.1:xxxx」と表示される。 その URL を Web ブラウザで開く。 数値入力欄の値を変えると、表示が即座に更新されることを確認する。
◆ ヒント
- コマンドがエラーになるときは、綴り、ファイル名、カレントディレクトリを確認する。
- ファイル名は server.R(大文字の R)とすること。www ディレクトリの中に index.html を置くこと。
- HTML 側の input の name 属性が、server.R の input$〜 の名前になる。
フォームの種類
/tmp/www/index.html の次の部分を書き換えて実行してみる。
<p>
<input type="number" name="n" value="10" min="1" max="150" />
</p>
- 1行テキスト
<input type="text" name="n" value="Write Text Here!" /> - ファイル
<input type="file" name="n" /> - チェックボックス
<label><input type="checkbox" name="n" value="red" />red</label> <label><input type="checkbox" name="n" value="green" />green</label> <label><input type="checkbox" name="n" value="blue" />blue</label> - ラジオボタン
<label><input type="radio" name="n" value="L" />L</label> <label><input type="radio" name="n" value="M" />M</label> <label><input type="radio" name="n" value="S" />S</label>
◆ 考察のポイント
- フォームの種類ごとに、input$n にはどのような値(数値、文字列、ベクトル)が渡るか。renderPrint の表示で確認する。
- renderTable に渡す処理を head(iris, input$n) のように変えると、UI とデータ処理の対応はどうなるか。
jQuery との連携
フォーム部品にフォーカスされたとき色付け
- /tmp/server.R のサンプル
library(data.table) library(shiny) shinyServer(function(input, output) { output$summary <- renderPrint({ paste("x =", input$x, ", y =", input$y) }) output$table <- renderTable({ data.table(iris) }) }) - /tmp/www/index.html の一部分(head 内に script を追加し、body を書き換える)
<script type="text/javascript"> jQuery( function(){ $("input").css("background-color","#efefef"); $("input").focus(function(){ $(this).css("background-color","#eff8f8"); }); $("input").blur(function(){ $(this).css("background-color","#efefef"); }); }); </script> </head> <body> <h1>HTML UI</h1> <form> <p> x = <input type="text" name="x" value="100"/> </p> <p> y = <input type="text" name="y" value="A"/> </p> </form> <div id="summary" class="shiny-html-output"></div> <div id="table" class="shiny-html-output"></div> </body> - 実行してみる
R システムで次のように操作する。
library(shiny) runApp("/tmp/") - Web ブラウザで表示してみる
入力欄をクリック(フォーカス)すると背景色が変わり、外すと元に戻ることを確認する。
ネットワークグラフの描画 (networkD3 を使用)
tree や graph を HTML や SVG に描画する。 以前は d3Network パッケージを用いていたが、開発が終了しているため、 後継の networkD3 パッケージを用いる(D3.js の読み込みも自動で行われる)。
- インストール
R システムで次のように操作する。
install.packages("networkD3") - 単体で使ってみる(HTML ファイルへの保存)
library(networkD3) Source <- c("A", "A", "A", "A", "B", "B", "C", "C", "D") Target <- c("B", "C", "D", "J", "E", "F", "G", "H", "I") NetworkData <- data.frame(Source, Target) p <- simpleNetwork(NetworkData, height = 300, width = 700, fontSize = 15) p saveNetwork(p, file = "/tmp/hoge.html") - Shiny と組み合わせて使ってみる
/tmp/net/ui.R のサンプル
library(shiny) library(networkD3) shinyUI(fluidPage( titlePanel('networkD3 Shiny Example'), p('This is an example of using', a(href = 'https://christophergandrud.github.io/networkD3/', 'networkD3'), 'with', a(href = 'https://shiny.posit.co/', 'Shiny'), 'web apps.' ), sidebarLayout( sidebarPanel( sliderInput('slider', label = 'Choose node opacity', min = 0, max = 1, step = 0.01, value = 0.5 ) ), mainPanel( forceNetworkOutput('networkPlot') ) ) ))/tmp/net/server.R のサンプル
library(shiny) library(networkD3) # データの読み込み(networkD3 付属のサンプルデータ「レ・ミゼラブル」の登場人物の関係) data(MisLinks) data(MisNodes) shinyServer(function(input, output) { output$networkPlot <- renderForceNetwork({ forceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source", Target = "target", Value = "value", NodeID = "name", Group = "group", opacity = input$slider) }) }) - 実行してみる
R システムで次のように操作する。
library(shiny) runApp("/tmp/net/") - Web ブラウザで表示してみる
スライダーを動かすと、ノードの不透明度が変わることを確認する。 ノードはマウスでドラッグできる。
◆ 考察のポイント
- スライダーを動かしたとき、サーバ側(server.R)ではどの処理が再実行されるか。Shiny のリアクティブ(反応的)な仕組みを考える。
- UI を R のコード(ui.R)で書く方法と、手書きの HTML(www/index.html)で書く方法の長所・短所を比較する。