bslib: input_task_button 소개

bslib의 0.7.0에서 새롭게 추가된 input_task_button에 대해 소개합니다.

R
shiny
bslib
ux
Author
Published

March 30, 2024

bslib

bslibとはbootstrapのcssをRで使えるようにしたパッケージです。

正確な原文の説明はTools for theming Shiny and R Markdown via Bootstrap 3, 4, or 5. で、ShinyとRmarkdown(もちろんQuartoを含む)で色んなテーマを活用することができます。

この記事ではbslibの活用方法の中でShinyに集中して説明します。

実際、Shinyは基本的にデザインのためbootstrapを使います。 しかし、Shinyはパッケージを構成してるコンポーネントと、関係が複雑に絡まっていて、かなり重いパッケージになってしまい、このため、アップデートで影響を受ける部分が多く、機能中心のアップデートをすることが知られています。

つまり、UIを主に扱うbootstrapの部分は5年前のバージョンである3.4.1バージョンを使っていて、別のテーマ設定をしない場合、特有のブルー/グレーのテーマを基本的に使うことになります。(最近のバージョンは5.3.3)

それでshinyでは停滞したUIをアップデートするため、UIを扱う別のRパッケージを作って上書きするように最近bootstrapの機能を提供するようになりました。

この記事ではbslibの主な使い方は説明しません。

actionButton

Shinyが提供する機能は本当に多様ですが、核心的な機能を挙げるなら、actionButtonを挙げることができます。

actionButton`とはユーザがボタンを押すとserverで予め宣言した特定の動作を実行する機能で、普通はユーザがデータをアップロードしたら、このデータを活用して計算結果を生成するために使います。

actionButtonの使用例としては下記のコードのように(?shiny::actionButtonで確認することができます)ユーザーが選択した観測数に合うヒストグラムを描くことができます。

library(shiny)

ui <- fluidPage(
  sliderInput("obs", "Number of observations", 0, 1000, 500),
  actionButton("goButton", "Go!", class = "btn-success"),
  plotOutput("distPlot")
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    input$goButton
    dist <- isolate(rnorm(input$obs))
    hist(dist)
  })
}

shinyApp(ui, server)

long actionButton

ところで、この actionButton の問題点の一つは、もし演算に時間がかかる場合、ユーザーはボタンを押して結果を待っている間は何もできないということです。

さらに、単純に何もできないだけでなく、ボタンがクリックされなかったと勘違いしてボタンを何度もクリックすることもあります。

もし、大容量の誘電体データを活用した計算のためのShinyであれば、1回の計算に分単位の時間が必要な場合もあり、これは様々な問題を引き起こす可能性があります。

特に、何度もクリックした場合、長い時間をかけて演算を終えた直後にまた同じ演算をまたやって、また待って、…という悪循環に陥ることもあります。

shiny with loading

actionButton`のこの問題を解決するため、色んな方法がありました。

  1. **progress indicatorを使う方法

この方法はshinyで基本的に提供するProgress Indicator UIを活用する方法で、演算の過程/段階が進むにつれて進行度をユーザーに見せることができます。

server <- function(input, output) {
  output$plot <- renderPlot({
    input$goPlot 

    dat <- data.frame(x = numeric(0), y = numeric(0))

    withProgress(message = 'Making plot', value = 0, {
      n <- 10

      for (i in 1:n) {
        dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
        incProgress(1/n, detail = paste("Doing part", i))
        Sys.sleep(0.1)
      }
    })

    plot(dat$x, dat$y)
  })
}

ui <- shinyUI(basicPage(
  plotOutput('plot', width = "300px", height = "300px"),
  actionButton('goPlot', 'Go plot')
))

shinyApp(ui = ui, server = server)

しかし、これは withProgress, incProgress または Progress などの関数やオブジェクトを時間がかかる演算に追加でコードを書かなければならないというデメリットがあります。

2.別のRパッケージを使う

Rのエコシステムには解決しようとする色んな問題があり、その問題毎のRパッケージがあると考えても過言ではないですが、actionButtonと演算結果の間の長い空白をUIに表記するための機能も同じです。

以前のprogress indicatorと似て追加コードを書いて解決する必要がありもう少しデザインや詳細設定をすることができるカスタム機能があると思ってください。

以下はいくつかの例示パッケージと事例です(アルファベット順)。

input_task_button

input_task_buttonは上の方法とは違ってactionButtonを拡張した機能で、actionButton`を押すと演算が進行中であることを知らせてボタンが無効になり、演算が終わったら再びボタンが有効になる機能を提供します。

何より一番大きな違いはactionButtonを置き換えることができるので追加コードを使う必要がないことです。

library(shiny)

ui <- fluidPage(
  sliderInput("obs", "Number of observations", 0, 1000, 500),
  # actionButton("goButton", "Go!", class = "btn-success"),
  input_task_button("goButton", "Go!", type = "success"),
  plotOutput("distPlot")
)

server <- function(input, output) {
  output$distPlot <- renderPlot({
    input$goButton
    Sys.sleep(5)
    dist <- isolate(rnorm(input$obs))
    hist(dist)
  })
}

shinyApp(ui, server)

input_task_button の使用のため、5行目の actionButton を6行目の input_task_button に置き換え、さらに、意図的に長くかかる演算を作るため、13行目の Sys.sleep() コードを活用して5秒を遅延させました。

input_task_buttonの使い方は次のようになります。

input_task_buttonactionButton` を無理なく置き換えることができますが、若干のパラメータ修正が必要です。

actionButton input_task_button 役割
inputId id ボタンID
label label ボタンラベル
icon icon ボタンアイコン
label_busy ボタン非アクティブ時のラベル
icon_busy ボタン非アクティブ時のアイコン
class type ボタンテーマ/色

まとめ

今回はbslibの最新機能であるinput_task_buttonと簡単な使用事例を紹介しました。

これは潜在的にユーザーエクスペリエンスを向上させる機能であり、既存のshinyでは追加コードを書かなければならない手間を解決してくれる機能だと思います。

特に、他のウェブアプリケーションとは違ってShinyでは大容量データ演算のため時間が長くかかる場合が多いですが、比較的貧弱なUI/UXを持っていて、既存のactionButtoninput_task_buttonに置き換える場合、これを補完するのに大きな助けになると思います。

今回の記事が参考になったかと思いますが、次の記事でまたお会いしましょう!

Reuse

Citation

BibTeX citation:
@online{kim2024,
  author = {Kim, Jinhwan},
  title = {Bslib: Input\_task\_button {소개}},
  date = {2024-03-30},
  url = {https://blog.zarathu.com/jp/posts/2024-03-30-input-task-button},
  langid = {en}
}
For attribution, please cite this work as:
Kim, Jinhwan. 2024. “Bslib: Input_task_button 소개.” March 30, 2024. https://blog.zarathu.com/jp/posts/2024-03-30-input-task-button.