Shiny app(R)中的互动目录输入 [英] Interactive directory input in Shiny app (R)

查看:415
本文介绍了Shiny app(R)中的互动目录输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个闪亮的应用程序,需要用户在本地机器上选择一个文件夹,其中包含要由应用程序处理的文件。



我正在使用一个解决方案这里。这在本地机器上工作正常,但如果将应用程序部署到闪存卡服务器,则不起作用。
该解决方案的作者证实,它只是设计用于本地Shiny应用程序,因为它使OS shell调用显示目录对话框。



I我想知道是否有一个不同的解决方案的目录对话框,这将在部署的闪亮应用程序(我正在部署到闪亮的普通照片)。



已编辑:请注意,我无法使用 fileInput 界面有两个原因:


  1. 该应用的用户不是技术人员,他们不知道哪个文件夹内的文件被应用程序使用。

  2. 所选文件夹可能包含所需文件所在的其他文件夹,这样就不可能一次性选择所有文件,即使fileInput界面具有多个选项已启用。

文件夹/文件结构不是我可以改变的东西,它是从医疗设备下载的,因此我唯一的可以期待用户是指定父文件夹,其余应在R代码内完成。

解决方案

这是一个基于使用webkitdirectory属性的工作示例。 Chrome浏览器支持此属性,Opera 49将在9月份推出Opera和Safari(移动和桌面设备)。
关于这个 here 的更多内容还有子目录。



它需要在ui.R中使用tags关键字。我已经通过上传三个csv文件进行了测试,每个文件都包含三个由昏迷分隔的数字。在本地测试,并在chrome和Opera上进行测试。这是代码:



ui.R

库(闪亮)
库(DT)

shinyUI(tagList(fluidPage(theme =bootstrap.css,
includeScript( /www/text.js),
titlePanel(文件夹内容上传),

fluidRow(
列(4,
wellPanel(
标签$ div(class =form-group shiny-input-container,
tags $ div(tags $ label(File input)),
标签$ div(tags $ label文件夹,class =btn btn-primary,
标签$ input(id =fileIn,webkitdirectory = TRUE,type =file,style =display:none;,onchange = )) )
标签$ label(No folder choosen,id =noFile),
标签$ div(id =fileIn_progress,class =progress progress-striped active shiny-file-
标签$ div(class =progress-bar)

),
verbatimTextOutput(results)

),
列(8,
tabsetPanel(
tabPanel(Files table,dataTableOutput(tbl)),
tabPanel(Files list,dataTableOutput tbl2))




HTML(< script type ='text / javascript'src ='getFolders.js'>< / script>)



server.R


$
库(DT)

ShinyServer(函数(输入,输出) ,会话){
df < - reactive({
inFiles < - input $ fileIn
df< - data.frame()
if(is.null(inFiles )
return(NULL)
for(i in seq_along(inFiles $ datapath)){
tmp< - read.csv(inFiles $ datapath [i],header = FALSE)
df< - rbind(df,tmp)
}
df

})
输出$ tbl< - DT :: renderDataTable(
df()

输出$ tbl2< - DT :: renderDataTable(
输入$ fileIn

输出$ results = renderPrint({
输入$ mydata
})

})

文本。 js

  window.pressed = function(){
var a = document.getElementById('fileIn');
if(a.value ===)
{
noFile.innerHTML =没有文件夹选择;
}
else
{
noFile.innerHTML =;
}
};

getFolders.js

  document.getElementById(fileIn)addEventListener(change,function(e){

let files = e.target.files;
var arr = new Array(files.length * 2);
for(let i = 0; i< files.length; i ++){

//console.log(files[i].webkitRelativePath );
//console.log(files[i].name);
arr [i] = files [i] .webkitRelativePath;
arr [i + files.length] =文件[i] .name;


}

Shiny.onInputChange(mydata,arr);

});

让我知道这是否有帮助。


I am building a shiny app that requires a user to select a folder on the local machine, which contains the files to be processed by the app.

I am using a solution proposed here. This works fine on a local machine, but does not work if the app is deployed to a shinyapps server. The author of this solution confirmed that it was only designed to work with local Shiny apps, since it makes OS shell calls to display a directory dialog.

I am wondering if there is a different solution for directory dialog, which will work on the deployed Shiny apps (I am deploying to shinyapps.io).

Edited: Notice that I cannot use fileInput interface for two reasons:

  1. The users of the app are not technical people and they do not know which files inside the folder are used by the app.
  2. The selected folder may contain other folders within which the needed files reside, such that it is impossible to select all files at once, even if the fileInput interface has the multiple option enabled.

The folder/files structure is not something I can change, it is downloaded AS IS from a medical device and therefore the only thing I can expect from the users is to specify the parent folder and the rest should be done inside the R code.

解决方案

This is a working example based on using the "webkitdirectory" attribute. At the moment the attribute is supported by Chrome, Opera and Safari (mobile and desktop) is should be supported in Firefox 49 to be released in September. More about this here It work with subdirectories also.

It require using the tags keyword in ui.R. I have tested it by uploading three csv files each contaning three numbers separeted by a coma. Test locally and on shinyapps.io wiht Chrome and Opera This is the code:

ui.R

    library(shiny)
    library(DT)

    shinyUI(tagList(fluidPage(theme = "bootstrap.css",
                      includeScript("./www/text.js"),
                      titlePanel("Folder content upload"),

                      fluidRow(
                              column(4,
                                     wellPanel(
                                             tags$div(class="form-group shiny-input-container", 
                                                      tags$div(tags$label("File input")),
                                                      tags$div(tags$label("Choose folder", class="btn btn-primary",
                                                                          tags$input(id = "fileIn", webkitdirectory = TRUE, type = "file", style="display: none;", onchange="pressed()"))),
                                                      tags$label("No folder choosen", id = "noFile"),
                                                      tags$div(id="fileIn_progress", class="progress progress-striped active shiny-file-input-progress",
                                                               tags$div(class="progress-bar")
                                                      )     
                                             ),
                                             verbatimTextOutput("results")
                                     )
                              ),
                              column(8,
                                     tabsetPanel(
                                             tabPanel("Files table", dataTableOutput("tbl")),
                                             tabPanel("Files list", dataTableOutput("tbl2"))
                                     )
                              )
                      )
    ),
    HTML("<script type='text/javascript' src='getFolders.js'></script>")
    )

    )          

server.R

    library(shiny)
    library(ggplot2)
    library(DT)

    shinyServer(function(input, output, session) {
            df <- reactive({
                    inFiles <- input$fileIn
                    df <- data.frame()
                    if (is.null(inFiles))
                            return(NULL)
                    for (i in seq_along(inFiles$datapath)) {
                            tmp <- read.csv(inFiles$datapath[i], header = FALSE)  
                            df <- rbind(df, tmp)
                    }
                    df

            })
            output$tbl <- DT::renderDataTable(
                    df()
            )
            output$tbl2 <- DT::renderDataTable(
                    input$fileIn
            )
            output$results = renderPrint({
                    input$mydata
            })

    })

text.js

window.pressed = function(){
        var a = document.getElementById('fileIn');
        if(a.value === "")
        {
            noFile.innerHTML = "No folder choosen";
        }
        else
        {
            noFile.innerHTML = "";
        }
    };

getFolders.js

     document.getElementById("fileIn").addEventListener("change", function(e) {

            let files = e.target.files;
            var arr = new Array(files.length*2);
            for (let i=0; i<files.length; i++) {

            //console.log(files[i].webkitRelativePath);
            //console.log(files[i].name);
            arr[i] = files[i].webkitRelativePath;
            arr[i+files.length] = files[i].name;


            }

            Shiny.onInputChange("mydata", arr);

    });

Let me know if this helps.

这篇关于Shiny app(R)中的互动目录输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆