ふんわり R-tips

ぜんぜんわからない、俺たちは雰囲気でRをやっている

Shinyにおけるコンポーネントのレイアウト方法

概要

Shinyにおけるコンポーネントのレイアウト方法を説明します。シンプルなサイドバーレイアウトから、階層付きのナビゲーションページまでHTML/CSSフレームワークのBootstrap 2で利用できるコンポーネントの配置がサポートされています。

  1. サイドバーとメインからなるシンプルなデフォルトのサイドバーレイアウト

  2. Shiny grid layout systemを用いたグリッドレイアウト

  3. タブセットtabsetPanel()ナビゲーションリストnavlistPanel()を用いたセグメント分けレイアウト

  4. ナビゲーションページnavbarPare()を用いた階層付きコンポーネント配置

サイドバーレイアウト

デフォルトのサイドバーレイアウトは、入力用のサイドバーと出力のための広いメイン領域で構成されています。サンプルアプリケーションの01_helloは、サイドバーにスライダー、メインにプロットを出力する例です。

f:id:phmpk:20161230151451p:plain

library(shiny)

fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),
    mainPanel(
      plotOutput("distPlot")
    )
  )
)

Code license:MIT

サイドバーレイアウトでは、サイドバーの位置がデフォルトでメインの左側ですが、以下のように、positionを指定することで位置を変えることもできます。

sidebarLayout(position = "right",
              
  sidebarPanel(
    # 入力用コントロール
  ),
  mainPanel(
    # 出力 
  )
)

グリッドレイアウト

サイドバーレイアウトも、グリッドレイアウトの一つです。fluidRow()で行を作成し、各行にcolumn()で列を作成します。列の幅は12分割で、fluidRow()関数で12以下の値を指定します。

fluidRow(), column(), wellPanel()を用いてサイドバーレイアウトを記述すると、以下のようなコードになります。

shinyUI(fluidPage(

  titlePanel("Hello Shiny!"),

  fluidRow(
  
    column(4,
      wellPanel(
        sliderInput("obs", "Number of observations:",  
                    min = 1, max = 1000, value = 500)
      )       
    ),

    column(8,
      plotOutput("distPlot")
    )
  )
))

column()の最初のパラメータは幅の大きさで、すべての幅の合計が12になるようにします。

以下の例では、上部にプロットを、下部に3つの列からなるプロット操作用の入力コントロールを配置しています。

f:id:phmpk:20170105203435p:plain

library(shiny)
library(ggplot2)

function(input, output) {
  
  dataset <- reactive({
    diamonds[sample(nrow(diamonds), input$sampleSize),]
  })
  
  output$plot <- renderPlot({
    
    p <- ggplot(dataset(), aes_string(x=input$x, y=input$y)) + geom_point()
    
    if (input$color != 'None')
      p <- p + aes_string(color=input$color)
    
    facets <- paste(input$facet_row, '~', input$facet_col)
    if (facets != '. ~ .')
      p <- p + facet_grid(facets)
    
    if (input$jitter)
      p <- p + geom_jitter()
    if (input$smooth)
      p <- p + geom_smooth()
    
    print(p)
    
  })
  
}
library(shiny)
library(ggplot2)

dataset <- diamonds

shinyUI(fluidPage(

  title = "Diamonds Explorer",
  
  plotOutput('plot'),
  
  hr(),

  fluidRow(
    column(3,
      h4("Diamonds Explorer"),
      sliderInput('sampleSize', 'Sample Size', 
                  min=1, max=nrow(dataset), value=min(1000, nrow(dataset)), 
                  step=500, round=0),
      br(),
      checkboxInput('jitter', 'Jitter'),
      checkboxInput('smooth', 'Smooth')
    ),
    column(4, offset = 1,
      selectInput('x', 'X', names(dataset)),
      selectInput('y', 'Y', names(dataset), names(dataset)[[2]]),
      selectInput('color', 'Color', c('None', names(dataset)))
    ),
    column(4,
      selectInput('facet_row', 'Facet Row', c(None='.', names(dataset))),
      selectInput('facet_col', 'Facet Column', c(None='.', names(dataset)))
    )
  )
))
  • 下部の入力コントロールを、3つの列に分割。

  • 2つ目のcolumun()にあるoffset = 1は、1つ目と2つ目の列の間にスペースを挿入するために指定。

  • titlePanel()ではなく、fluidPage()の引数titleに値を入力。

タブセット

タブセットは、tabsetPanel()により、タブでアプリケーションを分割するときに使用します。サンプルアプリケーションの06_tabsetsはタブセットの使用例です。

f:id:phmpk:20161230155218p:plain

shinyUI(fluidPage(
    
  titlePanel("Tabsets"),
  
  sidebarLayout(
    sidebarPanel(
      # 06_tabsetsの入力コントロール。
      # レイアウト説明には関係しないため省略
    ),
    
    mainPanel(
      tabsetPanel(type = "tabs", 
        tabPanel("Plot", plotOutput("plot")), 
        tabPanel("Summary", verbatimTextOutput("summary")), 
        tabPanel("Table", tableOutput("table"))
      )
    )
  )
))

タブはデフォルトで上部に配置されます。positionを指定することで、左右や下部にも配置することができます。以下に、下側に配置する場合の例を示します。tabsetPanel()でpositionを下側に指定しています。

tabsetPanel(position = "below",
  tabPanel("Plot", plotOutput("plot")), 
  tabPanel("Summary", verbatimTextOutput("summary")), 
  tabPanel("Table", tableOutput("table"))
)

ナビゲーションリスト(Navlists)

tabsetPanel()の代わりにnavlistPanel()を用いることで、タブではなくナビゲーションリストでコンポーネントを配置することができます。以下は、navlistPanel()の使用例です。

f:id:phmpk:20170105205522p:plain

図に対応するコードを示します。タブで指定するコンポーネントは、例なので空です。

shinyUI(fluidPage(
  
  titlePanel("Application Title"),
  
  navlistPanel(
    "Header A",
    tabPanel("Component 1"),
    tabPanel("Component 2"),
    "Header B",
    tabPanel("Component 3"),
    tabPanel("Component 4"),
    "-----",
    tabPanel("Component 5")
  )
))

ナビゲーションバーページ(NavBar Page)

上部に配置したナビゲーションバーによって、大きくShinyアプリケーションを分割して動作させることが可能です。以下の図はnavbarPage()によってナビゲーションバーを配置した例です。

f:id:phmpk:20170105205311p:plain

shinyUI(navbarPage("My Application",
  tabPanel("Component 1"),
  tabPanel("Component 2"),
  tabPanel("Component 3")
))

例なのでtabPanel()は空です。

セカンダリーナビゲーション

navbarMenu()を用いて、2段目までの深さのナビゲーションを配置することができます。1段目のナビゲーションバーに、タブパネルを追加します。

f:id:phmpk:20170105205705p:plain

shinyUI(navbarPage("My Application",
  tabPanel("Component 1"),
  tabPanel("Component 2"),
  navbarMenu("More",
    tabPanel("Sub-Component A"),
    tabPanel("Sub-Component B"))
))

ナビゲーションバーの追加オプション

navbarPage()に引数を指定して、オプションを追加することができます。

引数 説明
header すべてのタブパネルの上側の共通のヘッダとして表示するためのタグのリスト用タグ
footer すべてのタブパネルの下側の共通のヘッダとして表示するためのタグのリスト用タグ
inverse TRUEで、ナビゲーションバーのバックグラウンドを暗く、テキストを明るくする
collapsable TRUEで、ブラウザが940pixel以下になったときに、自動的にナビゲーションの項目をメニューとして掴む(スマホのような小さなタッチスクリーンで見るときに有用)