本記事は、Shiny Advent Calendar 2017の15日目の記事です。
Shiny100本ノックも気付けば第16弾まできました。
今回は、Shinyアプリケーションにファイルをアップロードする機能の実装方法について紹介します。
第11弾・第12弾にて、ドラッグ&ドロップによるファイルアップロードについて実践しました。
www.randpy.tokyo
www.randpy.tokyo
実は、わざわざ難しいドラッグ&ドロップでファイルをインプットしなくても、デフォルトで**fileInput**メソッドというエクスプローラーからファイルを選択できる機能があります。
ということで…。今回はfileInputメソッドを使ってファイルアップロードと、そのファイルを元にプロットを行うShinyアプリケーションを作成してみましょう。
また、サンプルコードはGithubにも置いてあります。
github.com
完成形はこんな感じ
まずはどんなアプリケーションが出来上がるのか、完成形の画像を貼ります。何もファイルを選択していない状態
ファイル選択後
プロット後
はい、このようなShinyアプリケーションです。
以下とデータ入力の仕方が変わっただけで、後は一緒なので分かりやすいかと思います。
www.randpy.tokyo
また、fileInputメソッドを使うことで実装も相当楽になります。
ソースコード解説
ドラッグ&ドロップの場合は、Javascriptファイルが必要でしたが、今回は不要です。ui.Rファイルと、server.Rファイルのみで実装可能です。
ui.Rのソースコード
まずは、ui.Rのコードを紹介します。library(shiny) shinyUI( fluidPage( sidebarLayout( sidebarPanel( fileInput("file", "Choose CSV File", accept = c( "text/csv", "text/comma-separated-values,text/plain", ".csv") ), tags$hr(), h2("プロットするデータを選択"), htmlOutput("colname1"), htmlOutput("colname2"), actionButton("submit", "プロット") ), mainPanel( tabsetPanel(type = "tabs", tabPanel("Table", tableOutput('table')), tabPanel("Plot", plotOutput("plot")) ) ) ) ) )
以下の部分がファイルをエクスプローラーから受け取る部分です。
fileInput("file", "Choose CSV File", accept = c( "text/csv", "text/comma-separated-values,text/plain", ".csv") )
fileInput("server,Rに送る変数名", "表示するテキスト", accept = "どんなファイル形式を受け取るか")
という風に書いいけばOkです。
今回はserver.Rに送る変数名をfileとしたので、server.R側で「input$file」と書くことで参照が可能です。
テーブル表示部分やプロット部分は第12弾紹介した記事内容と同じなので説明は省略します。
server.Rのソースコード
続きまして、server.Rのソースコードを紹介します。server = function(input, output, session) { observeEvent(input$file, { csv_file = reactive(read.csv(input$file$datapath)) output$table = renderTable(csv_file()) output$colname1 = renderUI({ selectInput("x", "x軸方向", colnames(csv_file())) }) output$colname2 = renderUI({ selectInput("y", "y軸方向", colnames(csv_file())) }) }) observeEvent(input$submit, { name = names(input$file) csv_file = reactive(read.csv(input$file$datapath)) x = csv_file()[input$x] y = csv_file()[input$y] output$plot = renderPlot({ plot(x[,1], y[,1]) }) }) }
構成は前回と一緒ですね。
変わったところは、以下のファイルの受け取り方。
csv_file = reactive(read.csv(input$file$datapath))
input$file変数の、datapathという変数にテキストデータが格納されているので、上のように取り出して、csvファイルとして読み込みます。
ここまでできたら後は第12弾と全く一緒です!
読み込んだcsvファイルの列情報を元に、何をプロットするのか選択するためのUIをui.Rに返します。
その後ui.Rにてプロットボタンが押されれば、その情報を元にrenderPlotにてプロットを返しています。
このあたりも第12弾で解説したので、説明は省略させていただきます。
まとめ
今回はfileInputメソッドを使って、ファイルアップロード機能を作りました。ドラッグ&ドロップによるファイルアップロードの場合は、どうしてもJavascriptの知識が必要となるのでハードルは高いかもしれませんが、こちらであればかなり簡単に書くことができます。
できれば両方実装できていると幅が広がって良いと思いますが、まずはfileInputを使ってアップロード機能を実装するというのが良いかもしれません。
是非試してみてください!