简体   繁体   中英

Automatic multi-file download in R-Shiny

I'm trying to figure out how to get a data.frame to subset itself and then write a .csv file for each subset. I'm writing a shiny app which will generate template files for different instruments, and I need to be able to get a file for each batch/plate/whatever. Obviously, we could do a manual sort, but that kind of defeats the purpose.

In example, say that I have a data.frame with 4 columns named 1) PlateID, 2) SampleName, 3) Well and 4) Comments and I want to subset by the PlateID such that each individual plate will have it's own file.

output$multiDownload <- renderText({
#templateData() just loads the data, nothing special;
#If you wanna see it let me know, but I think it's bulky
  tempData <- templateData()
  if(is.null(tempData)){return(NULL)}

    #If there are more than one plate, subset by plate ID and write each file
    if(max(tempData$PlateID) > 1){
    for(i in 1:max(tempData$PlateID)){
        tempSubsetForWrite <- subset(tempData, tempData$PlateID == i, select =   c("names", "well", "comments"))
        write.csv(tempSubsetForWrite, file = paste0("file ", i, " of ", max(tempData$PlateID), row.names = FALSE)
      }
  } else {
    write.csv(tempData, file = "file", row.names = FALSE)
  }
}) 

So I want to add a few features and I'm not sure how to approach them. First, I would like to have better control of where the data is written. I would like it to go into the same file as my input files, but I'm not sure how to force this? I tried doing something like:

inFile <- input$templateGenerationFile
write.csv(tempData, paste0(inFile$datapath, "/file ", i, " of ", max(tempData$PlateID))

but in inFile$datapath appears to be a temp folder/file which is generated and not a direct link to the original file!

Also, I'm wanting to write something that will act like a downloadHandler in the sense of having a button which will download the files upon clicking, but I don't think I can use that in this scenario because I am writing multiple files. If I'm wrong then PLEASE let me know, as that would make life easier. I am thinking that I will use an actionButton and a counter variable so that the counter is the value of the button + 1 until the button is activated, in which case they are equal until the end of the function. Obviously I would have a conditional which handles the rest, but that is trivial so lets focus on the file subset and download!

Thanks!

The zip() doesn't work for me but it is easy with the tar function..

      output$downloadData <- downloadHandler(
         filename = function() { paste("filesintar", '.tar', sep='') },
         content = function(file) {
           tar(file,"./dirwheremyfilesare") #  no inlcuye rutas hasta raíz.
         }
       )

hope this will help. I try with zip instead of tar but I've got an error :

        zip(file, paste("./dirwheremyfilesare/",dir("./dirwheremyfilesare"),sep=""))

Thank u.

Antonio M.

I modified @amaurandi answer to complete OP question, adding some extra decorations that I found worked for me. Warning, I also used a plyr function, dlply , to simplify a bit.

I reproduced the problem with zip throwing an error (cannot explain it), but tar can be made to work. In principle these are platform independent functions in R, but that also implies everything is setup correctly with your installation.

Example based on OP starting point and previous answer snippet from @amaurandi

output$multiDownload <- downloadHandler(
  filename = function(){
    # Time-stamp tar filename
    paste0("platetables-", gsub("\\D", "_", Sys.time()), ".tar")
  },
  content = function(file){
    # Loads the data. Could be reactive.
    tempData <- templateData()
    if(is.null(tempData)){
      # Protect against empty data.
      return(NULL)
    }
    plateNames = unique(tempData$PlateID)
    tempdir = tempdir()
    dlist = plyr::dlply(tempData, "PlateID", function(x) x[, c("names", "well", "comments")])
    for(i in plateNames){
      write.csv(x = dlist[[i]], file = paste0(tempdir, "/", i, ".csv"), row.names = FALSE)
    }
    tar(tarfile = file, files = tempdir)
  }
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM