2

I have an RStudio Shiny app that saves user data in a subdirectory where my shiny app is hosted. What is the best way to store the data and access it?

The relevant part of the code is something like this:

# Save all answers after click on "submit"
observe({
  if(is.null(input$submit) || input$submit == 0) {return()}
  filename <- paste0("/data/answers-",input$userName, "-", as.numeric(Sys.time()), ".RData")
  save(values$A, file = filename, compress = "xz")
})

The app works: the data is successfully saved in the data subdirectory on the server.

Edit: I save the data as .RData, assuming that's a natural approach. If I save the data as .csv, it looks like this:

"What do you think about this?","Excellent","Excellent"
"What do you think about that?","Excellent","Excellent"
"User Unique ID","ABC123","DEF456"

except that there are more rows and more columns.

One approach would be to periodically download the data from the server and delete it on the server if it exceeds a critical size (to prevent it from taking up too much space). How best to do that?

Any tips on database management are welcome.

I am cross-posting from shiny-discuss, where my question has not yet generated any reaction:

https://groups.google.com/forum/#!topic/shiny-discuss/gOEtUsh00Qs

PatrickT
  • 10,037
  • 9
  • 76
  • 111
  • Can you give an example of what the output for one user might look like? I would not save to separate files. Either append to a txt or csv file or store in a database. These questions/answers on SO [1](http://stackoverflow.com/questions/15390565/rsqlite-takes-hours-to-write-table-to-sqlite-database) and [2](http://stackoverflow.com/questions/21668640/how-to-append-to-an-existing-file-in-r-without-overwriting-it/21668764#21668764) might be helpful. – Vincent Feb 12 '14 at 05:11
  • @ Vincent, thanks for your suggestions, let me edit the question and clarify :-) – PatrickT Feb 12 '14 at 17:52
  • Doing things column-wise seems unusual. Why not set up a CSV with columns for ID, question 1, and question 2, and then each row is a user with their responses? That would allow for more easy updates, new data can just be appended to the end of the CSV. – Gregor Thomas Feb 12 '14 at 18:18
  • @PatrickT did you see the links to the SO posts about databases in my previous comment (click the 1)? That should be helpful. I am not sure how you append column wise. The usual append is by row and would happen each time a user submits (see link 2 in my previous comment). It seem shujaa and I agree :) Everytime the app saves to the file you could add file.info("myfile.csv")$size and if that exceeds a certain size email you or email the file to you or something and then delete the file. – Vincent Feb 12 '14 at 18:23
  • @Vincent, thanks for your suggestions. Yes I have followed the links on database management, and the post about copying chunks to an sql might be useful. However, my most pressing question is rather primordial, probably so dumb that I did not get understood: with my data stored on the server, how could I download it in a "systematic" way? I know how to "manually" point a url to it and save to disk, but I was looking for some lines of code I could run "automagically" or perhaps a timer I could set have the data sent to some place like dropbox, my email, or whatever smart people do ;-) – PatrickT Feb 12 '14 at 18:45
  • @shujaa, thanks for the suggestion, I'm not sure why it matters if the data is arranged column-wise by user as opposed to row-wise since it's very simple to transpose it, what am I missing? thanks :-) – PatrickT Feb 12 '14 at 18:46
  • @shujaa, Here is an illustration of the sort of app and data I want to develop: `library(shiny)` `runGist("https://gist.github.com/ptoche/8962091")` – PatrickT Feb 12 '14 at 20:06
  • 1
    @PatrickT Before I even look at this I would like to know why you want to use Shiny for this? For a basic survey there are much easier/nicer options such as google forms, survey monkey, qualtrics, or even django (which is what I use). FYI I get the following error (Shiny .8.0.99) running the gist: Warning in read.table(file = file, header = header, sep = sep, quote = quote, : incomplete final line found by readTableHeader on 'survey.csv' Error in takeSingletons(result, shinysession$singletons, desingleton = FALSE) : argument "shinysession" is missing, with no default – Vincent Feb 12 '14 at 22:14
  • @ Vincent, I'm using shiny because that's what I've been using lately and I'm happy to learn about it. I know about google forms, don't know the other ones, so thanks for the pointer. I also experienced the error you're having, not sure what's causing it, but it disappeared after I updated all my packages. I had no error 2 weeks ago. I have no error now after updating everything. There is no error on the server, which is where the survey will be stored and used. Thanks for pointing out the error, are you by any chance using the latest RStudio? I reverted to the previous version just in case. – PatrickT Feb 12 '14 at 22:23
  • @ Vincent, I had accidentally and rather stupidly copied an in-progress version to the gist, duh, so that's where the errors were coming from. Sorry for the waste of time. I hope it's error free now. I'm going to look into the suggestions you and Stéphane made and report back as soon as possible. – PatrickT Feb 15 '14 at 04:57

1 Answers1

1

Sorry. Comment had too many characters and this is a bigger box. If you want to append data to a file (e.g., csv) that will happen per row as in the link I provided. So you should t() your data before sending to file. To have scripts run at fixed time intervals do a search for R and Cron (for mac and/or linux). It might be easier to do this in your shiny app with invalidatelater. Setup an observer that runs every hour for example. If the file is larger than X (using file.info("myfile.csv")$size) then do something (e.g., use file.copy to move it to your dropbox account if you have dropbox installed on your server. Or email it. I haven't used email with R but this looks promising.

In sum: Try some stuff and let us know if you get stuck :)

Community
  • 1
  • 1
Vincent
  • 5,063
  • 3
  • 28
  • 39
  • thanks a lot for the suggestion. As I wrote in my earlier comment, I have the saving side of things running, my problem is handling the saved file. I'm very interested in your suggestion to have an observer copy every hour or every time the file exceeds a certain size, do you have sample code for that? I don't use dropbox, but I will if you think it's the way to go. It sounds cleverer than email, no? Let me post a link to a gist with my full code so we don't talk past each other. Will post it below my question. Thanks! – PatrickT Feb 12 '14 at 20:05
  • 1
    a short while back I received a suggestion to use a database table rather than csv, which is why I mentioned `database management` in my question, but it's not something I've done before, so I haven't tried it. Ref. `https://groups.google.com/forum/#!topic/shiny-discuss/jnYTe0rHbqI` – PatrickT Feb 12 '14 at 20:21
  • Every 24 hours would be: `invalidateLater(86400000, session)` the units are milliseconds ... that's a big number ... – PatrickT Feb 12 '14 at 20:25
  • 3
    Hi @PatrickT & Vincent, the functions `reactiveFileReader` and `reactiveTimer` could be helpful – Stéphane Laurent Feb 12 '14 at 21:40