R Shiny:Drag & Dropまとめ

Shinyは手軽にWeb実装を実現するパッケージなのでDrag&Dropを実装したくなる場面が多々発生します。

今回は、D&Dを実現する方法をまとめてみました。

ShinyでDrag&Dropを実現する方法にはなにがあるのか

最もありがちな場面は、データ分析用の元データファイルをWebにアップロードする時にドラッグ&ドロップで行うようなケースです。
また、回帰モデルで変数選択を試行錯誤するためのUIを設計する場面では、説明変数を選択しては都度その結果を見てみることを繰り返す必要があることから説明変数の候補一覧からドラッグ&ドロップで説明変数を選択する画面を実装したくなります。

このような時にドラッグ&ドロップの実装に使える方法はいくつかあります。

Shiny標準ツール

version1.0.4からファイル読み込み関数 fileInputでドラッグ&ドロップが実装されています。

使い方はシンプルで、ファイル選択時の窓に直接ファイルをドロップすればOKです。
Shinyの組み込み関数として提供されているのでこの用途ではこれで十分かと思います。

こちらは@Np_Ur_さんのブログでも紹介されていますね。

ちなみに、アップロードホルダーのアピアランスをカスタマイズ(色を変えたりサイズを変えたり)ということも可能なので、
自分のアプリに合わせて変えてみるのもよいと思います。例えば以下のような記事も参考になります。

ところが、ファイルのドラッグ&ドロップ以外ではShiny純正機能としては提供されておらず、自分で作り込むかパッケージの利用が必要になります。

以下パッケージの特徴を紹介します。

ShinyDnD

多分最も標準的なパッケージと思われますが、2016年から開発が止まっておりやや古くなっていますが、
CRANからインストールできます。

細かい制御が標準オプションにはついていないのでシンプルな使い方としては手頃でよいのではないでしょうか。

shinyjqui

jqueryを使って、要素のドラッグ、リサイズ、show/hideなどUIをリッチにする機能がいくつかパッケージになっています。
こちらもCRANからインストール可能です。

こちらのパッケージは、細かい要素のドラッグ&ドロップよりも、大きめの要素(グラフなど)の並べ替えなどの要素に適していそうですが、
本サイトで実現したい「変数名をドラッグで選ぶ」などの用途ではチョット使いづらいと感じました。

dragulaR

dragulaRは軽くてロバストと好評なdrag&dropのjsライブラリであるdragulaのwrapperになっています。
2016年に最初のバージョンが出ていますがここ1年は更新が止まっているようです。

ただし、ドラッグやドロップのエレメント情報の取り出しや、リアクティブ環境での取り扱いにやや癖があります。
また、stackoverflow.comにも情報が少ないため、オリジナルdragulaの知識がないと結構試行錯誤が必要になると思われます。

このパッケージを使えば説明変数を選ぶなどの用途にも使えますが、ドロップ側の受け入れ要素数を一つに限定するなどの必須設定の方法が
めんどくさそうだったので私は結局以下にあげるdragulaSelectRを利用しています。

dragulaSelectR

現在の目的に最も適していると思われるドラッグ&ドロップの一押しパッケージです。

これは実質2019年になってからリリースされた新しいパッケージです。
こちらもdragulaのwrapperですが、dragulaRよりはより直感的で使いやすいパッケージになっています。
エレメントのロック、ドロップ可能最大数の設定、二つのドロップ窓のリンクなど細かいオプションも豊富です。

CRANには掲載されていないので、インストールにはdevtoolsを使ってください

なお、このパッケージはドラッグ側の要素とドロップ側の受け入れ可能要素を別途指定する必要があるのですが、ドロップ側に要素が移動してもドラッグ側に同じ要素が残り続けますので、
ドラッグ側のリストから消したい場合は別途処理が必要です。

こちらのパッケージの問題は、dragulaRよりも新しいこともありネット上にオフィシャル以外にはほとんど情報が
存在しないことです(googleで数件のみヒット)。全くのShiny初心者にはチョットきついかもしれませんが、サンプルも豊富なのである程度触っているかたならば想像力で
理解可能な比較的プレーンなパッケージです。

アップデートが盛んで安定してつかえており、カスタマイズも比較的やりやすいので重宝しています。

今後dragulaSelectRの使い方について(理解できた範囲で)少し説明したいと思います。