Shiny DTのテーブルのダウンロードボタン

Shinyできれいなテーブルを作る際には DT (dataTable)パッケージを使うことが多いかと思います。

本日はこのDTで作ったテーブルをCSVなどで出力するためのダウンロードボタンの作り方についてです。

以下のようなイメージのダウンロードボタンとなります。

f:id:okdata:20190901101704p:plain:w400

dataTableの基本コード

まずはDTによるテーブル出力の基本形から確認します。

Shinyの公式ページにあるミニマムコードは以下の通りです。

組み込みデータmtcarsを使ったかなりさっぱりしたデータテーブルですね。

library(shiny)
library(DT)
ui <- basicPage(
h2("The mtcars data"),
DT::dataTableOutput("mytable")
)
server <- function(input, output) {
output$mytable = DT::renderDataTable({
mtcars
})
}
shinyApp(ui, server)

DTテーブルにダウンロードボタンをつける

ではこのミニマムサンプルを変更してテーブルデータをダウンロードする
ボタンをつけてみます。

変更点はDT::renderDataTable( )の中身だけです。

今回のテーマであるダウンロードボタンを追加する際に必要な変更点は3つほどあります

  1. extensions = 'Buttons'の追加

ボタンをつける際に必要となるエクステンションの指定です。

  1. dom = "B"の指定

エクステンションでButtonの利用を追加しましたがoptions = でdomに
Bを指定する必要があります。B以外でもDOMに指定している他のアルファベットを
変更するとテーブルに出てくるページネーションボタン、フィルターなどが変わります。

  1. buttons =で表示したいボタンを指定する

ここにあるもの以外にもcopyprintなどもあります。

library(shiny)
library(DT)
ui <- basicPage(
h2("The mtcars data"),
DT::dataTableOutput("mytable")
)
server <- function(input, output) {
output$mytable = DT::renderDataTable(
mtcars,
extensions = 'Buttons',
options=list(
dom="Blfrtip",
buttons = c("csv", "excel", "pdf")
)
) # end of renderDataTable
}
shinyApp(ui, server)

ダウンロードボタンをかっこよく

上記の例ではボタンを3つ横並びにしましたが、まとめてプルダウン的に表示することができます。

以下の例を参考にしてください。この例ではcopyのよこにDownloadボタンが出現しており
そこをクリックするとcsvなどのフォーマットが選べる形になっています。

options=list(
dom="Blfrtip",
buttons =
list("copy",
list(
extend = "collection",
buttons = c("csv", "excel", "pdf"),
text = "Download"
)
)
)

ダウンロードボタンをさらに使いやすく

これまでのコードではダウンロードするさいにファイル名を入れる必要がありましたが、
デフォルトのファイル名をあらかじめ指定することも可能です。

以下の例を参考にファイルタイプ別にfilenameを指定すればOKです。

options=list(
dom="Blfrtip",
buttons =
list("copy",
list(extend = 'collection',
buttons = list(
list(extend='csv', filename = 'car-csv'),
list(extend='excel', filename = 'car-xls')
),
text = 'Download'))
)

ダウンロード時のダウンロード件数が少ない件

これまでのコードはダウンロードボタンのカスタマイズについてですが、
実際にやってみるとダウンロドできる件数が少ないことに気づきます。

これは、DTテーブルは標準ではサーバー側でレンダリングが行われるので、
ダウンロードボタンは画面で出ている部分(UIで読み込んだ部分)しかデータのダウンロードが
できないためです。例えば、1ページあたり10行ずつ表示させているようなケースでは10行しか
ファイルに吐き出されません。

この回避のためには, server=FALSEの指定を行って、UI側にレンダリングさせる必要があります。詳細は
ここ
を参照してください。

ただし、大きなテーブルの扱うのは負担が大きくなるため現実的ではありませんので
注意して使ってください。

  output$mytable = DT::renderDataTable(
mtcars,
server = FALSE,
extensions = 'Buttons',
options=list(
dom="Blfrtip",
buttons =
list("copy",
list(extend = 'collection',
buttons = list(
list(extend='csv', filename = 'car-csv'),
list(extend='excel', filename = 'car-xls')
),
text = 'Download'))
)
)

もう一つの方法は画面に出ている部分しか出力できなら「全件画面に出力してしまえば良いではないか」という
強引な方法もあります。

以下のサイトを参考に組み込んでみました。

出力件数を選べるプルダウンにALLを入れた点がポイントです。ここでALLを選んでダウンロードすれば
全件出力が可能となる(はずですが、大きなデータセットでは負担が大きすぎて無理筋かとは思いますが、、、)

options=list(
dom="Blfrtip",
buttons =
list("copy",
list(extend = 'collection',
buttons = list(
list(extend='csv', filename = 'car-csv'),
list(extend='excel', filename = 'car-xls')
),
text = 'Download')),
lengthMenu = list( c(10, 20, -1)
, c(10, 20, "All")
),
pageLength = 10
)

結局

チョットした10行程度の推計結果のパラメータ出力などには簡便な手法で簡単に実装できるので
良いかと思いますが、大きなデータセットのダウンロードにはやはりdonwloadHandlerで実装するのが
王道かと思います。

このあたりはいろいろな手法が議論されていますので例えば以下をご参照ください。

おまけ

テーブルをいろいろカスタマイズできるdomの指定ですが、ここの並び順変えるとテーブルに出力する位置を調整することができます。

この要素(アルファベット)の並び順が”概ね”表示の位置に反映されるということです。
ちなみにBlfrtiplfrtBipB(=button)t(=table)の後ろにしてみるとボタンの位置がテーブルの下に変わります。

細かい調整をするためにはCSSを変更する必要ありますが軽めのレイアウトアレンジ程度ならこれでも
いけます。