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.