LoginSignup
4
4

More than 5 years have passed since last update.

Shinyで同じ階層構造のUIを連続して生成する

Last updated at Posted at 2017-08-04

※20180205 データフレームの取り扱いを変更
以下のようなイメージで同じ要素グループを連続して並べる時のコードです。それぞれのカタマリで個別のnumericInputを参照し、それぞれヒストグラムを描画しているデモです。
スクリーンショット 2017-08-04 14.28.16.png

app.R
library(shiny)
# UI description
rep <- 5
ui <- fluidPage(
  lapply(1:rep, function(i) {
    div(
      numericInput(paste0('n', i), paste0('num=', i), i ^ 2 * 100),
      plotOutput(paste0('p', i))
    )
  })
)
# Server logic
server <- function(input, output, session) {
  dflist <- list()
  lapply(1:rep, function(i) {
    output[[paste0('p', i)]] <- renderPlot({
      dflist[[i]] <- rnorm(input[[paste0('n', i)]])
      hist(dflist[[i]])
    })
  })
}
shinyApp(ui, server)

ポイント

for/whileは使用しないほうが良い

描画とreactivityの演算はループで指定した順番とは別で行われるため(データがステートレスにならなくてはいけない)、逐次を想定した記述をしてもうまくいきません。ステートレスということはlapplyでやりきれる、ということですので頑張ってlapplyで記述しましょう。生成数を動的に変更するためにinsertUIを使用した例はこちらで記述しています。

繰り返しに複数要素を入れ込むときはdivる

複数繰り返しはdiv()でくくりましょう。仮想的にクラス化されるshinydashboard::box みたいな関数でも同じことが実現できます。

div(
numericInput(paste0('n', i), paste0('num=', i), i ^ 2 * 100),
plotOutput(paste0('p', i))
)

異なるデータセットを使用する場合は親リスト以下にデータフレームを格納する

dflist <- list()
まずデータフレームを格納するリストを作成し
dflist[[i]] <- rnorm(input[[paste0('n', i)]])
その後それぞれのデータフレームをその下に格納していきます。ちなみにreactive contextに触れないようにisolateでくくるか、例のようにcontext外になるようplotの中に入れてしまうかする必要があります。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4