Speedup UI in loading shiny - r

In global.R file I am reading some 10-12 excel files, some user defined functions, modules and doing some data manipulation (not so heavy task) on top of that. I want to speed up loading shiny app. I was thinking if I save it in .RData and then do load("mydata.RData", envir = .GlobalEnv) instead of reading excel files and sourcing functions in global.R. Would it improve loading time of shiny app? I am fine even if UI appears but server still loads. I am more interested in showing UI to the user instantly and user can wait for some calculation. I am using docker for production, hence mainly interested in UI loading time as container takes some time to spin up which user has to wait and then loading the app also takes time.

That is a big topic and there are several points in which you can improve your Shiny-App, so that it runs faster.
The first idea would be, to put every tab into a module. Meaning that the code you normally run within your ui.R will get a lot shorter. Thus the app gets faster, since the plots, files, etc. what is needed within this module, just gets loaded once the user clicks on that tab.
Make your app more efficient by using data.table. This package is specifically designed for faster usage. You can even combine it with dplyr. In your case try loading your files with the data.table::fread() command.
When it comes to plotting you can even use JavaScript's D3. There is a package called r2d3, which enables you to use JS's D3 to plot within your Shiny-App.
Convert the excel-files into a more machine readable format, like .rds. This also increases the loading speed.
I would suggest, you once use the profvis package and run your Shiny-App with it. It will allow, after you've loaded your app and closed it again, to see what exactly took so much time. Maybe it was not the loading after all, but a different problem instead? Then you could go from there.

Related

Shiny apps in R: how to structure them correctly

I created my first Shiny app, which runs perfectly in my laptop.
However, I need to submit it to my professor and I want to make sure he will be able to run it.
I have a UI file, a server file, a global file and a process file.
The process file stores the data preparation.
The global file reads two RDS files which are the datasets that I use in the server.
Where should my libraries be loaded? For example, the app does not run without leaflet, how can I ensure the libraries are run automatically?
My RDS files are saved to my local drive, which means that my professor will need to change the path in order to use them, how can avoid this?
Shall I put the UI, server and global into one R script or is it ok to have them onto two different scripts?
Thank you!
As you describe your current set up, the most obvious place to load your libraries is at the start of your global file. (Or at the start of app.R if you move to a single file configuration.) Though not exactly what the reprex package is designed for, you could probably use reprex to make sure that your code is reproducible and independent of anything you may have overlooked. (You've already identified the obvious issue with data files.) Look here for more information on reprex.
Indeed. This is a problem. If you must load the data from files, you need to find a way of providing them to your professor. Telling him to edit your code by hand is not a good way to start. Exactly how to do this depends on the infrastucture your institution has set up, so it's difficult to advise you what to do. Do you not have a shared area for your course? Ask your fellow students - or even your professor.
Whether you bundle the app in a single file or in seperate files is really a matter of choice. I don't think there's a wroing way and a right way. For me, the deciding factor is usually the size of the app. Large apps get several files. For small apps, separation is just an unnecessary complication. Another factor - that doesn't seem to be an issue here - is whether I see the app as a potential front end for some methodology that might be worthy of its own package. In that case, I develop the app as a front end, and the package itself as separate entities.
Question 1 and 3 depend on criteria for code quality like performance and maintainability. When the code grows, there will come the point when it is more difficult to handle all code in one file. Once it grows even further you will encounter the point when you need split the app into modules to keep your code easy to maintain.
Regarding libraries I advise declaring them at the entrance point of an app (though, basically, that is a matter of taste and style). That way, you provide maximum clarity regarding the dependencies of the app. Again, if the app becomes very large and not all parts of the app rely on the same packages, it could improve performance and maintainability that each part loads the packages as required. It could give you a performance advantage when you do not need to load all packages at once. However, that is probably only true for very large apps.
However, since this all seems to be an exercise at university, I doubt that your app will reach higher levels of complexity.
Question 2: In a shiny app you can provide fileInput widget. This SO question shows you how.

R/Shiny: View full stack/execution log

I'm debugging a Shiny web app, and would like to see the entire control flow/execution path over the course of rendering and updating the generated website.
Is there a way to capture/print/dump-to-file every line of code that is executed in the process of rendering/updating a Shiny app? It would also be good (maybe better?) to see every line of R code parsed by the running R interpreter instance; I'm not concerned about length of this output, and would prefer to get things as verbosely as possible.
I have looked into the stack tracing Shiny functions but these seem to be intended for error catching/handling/reporting. The app is not generating errors/warnings, just setting some variables to NULL at some point when they shouldn't be, so I'm not sure if this is the right approach. These stack tracing functions also seem to be more localized, designed to operate within a given reactive variable/function/render rather than following the control/execution flow across differing reactives/rendering functions in an app.
This app is a large, company-internal app so I cannot give a MRE/MWE.
I finally found the profvis package that does more-or-less exactly what I want by taking a snapshot of the execution stack at a fixed time interval (default 10ms). I'm still working on using this tool to debug, but I believe this will get me there and would also be useful to others debugging Shiny apps that need more than browser() and/or reactlog.
Specifically, I have been doing:
#install.packages("profvis")
library(profvis)
exec_log <- profvis(runApp("myShinyApp"))
...interact with the myShinyApp web page enough to trigger the bug, then interrupt execution...
print(exec_log)

R Shiny Server - set a loading animation on application startup

I've used shinyapps.io in the past and it provides a loading animation (spinner) while the application starts up. This is useful because I load 200MB of .RData-files into the memory (once on startup, not for every server()). This takes up to 40 seconds (in future, I will transition towards storing the data in a database, but for now this is what I got).
For other applications, I've used the docker image rocker/shiny and wanted to fully transition to a Docker-based approach and put all my shiny applications on one server and move away from shinyapps.io. However, the one issue I have with this application is that it does not display a loading animation while it starts so the user is left with a grey screen for a good 30-40 seconds while the data is loaded in the background.
As for the code, I load all data and then I source ui.R and server.R before running shiny::shinyApp(ui = ui, server = server).
Does any of you know a way to specify a loading animation on startup of the application (I haven't found anything in the server configuration itself but I could have overlooked something)? Or have you found a nice workaround to achieve the desired result?
So what I ended up doing was to follow this workaround suggested here: http://www.mazsoft.com/blog/post/2018/01/01/show-progress-bar-when-pre-loading-data-in-shiny-app
The idea is that we initialize all data variables with NULL. Then there is a readData() function outside of server and ui where we load all the data into the global variables and at the beginning of the server function block we check if one of our data variables is.null() which would lead us to call the readData() function.
It is an okay solution for my problem as it's a nice workaround, yet I wasn't able to figure out how to actually display a loading animation on startup, just while loading the data. I hope this helps people with a similar same problem.

Shiny progress bar during loading RData, Package?

I am not sure if I can show any reproducible example here, however let me narrate the issue I am facing with my Shiny app.
I have a Shiny app, which is basically data driven. All my required data is saved in an RData file which is placed in WWW folder. When user put my Shiny app's address (which is hosted on Amazon AWS) i.e. when my Shiny app starts, that RData file is loaded onto R, and then subsequent calculation starts.
The issue is that, my RData file is of quite huge size ~50MB. So R takes quite long time to load that onto memory. From User's perspective, he/she is not sure what is happening behind the screen, that makes some of them leave my App.
So I was thinking if I can put some progress bar to show User something is happening, as that Progress bar would be displayed only during the time when R is loading my RData file. I am aware of various Progress bar schemes available for Shiny, however as far as I know they are to display progress only during calculation (e.g. simulation) not during loading something.
Any idea if it is possible to put some Progress bar during loading RData, package etc?
Thanks for any pointer.
maybe a bit late but I share what I used, should it be useful for someone else.
Take a look at the shinycssloaders package (https://github.com/andrewsali/shinycssloaders).
By adding a simple function withSpinner and set a few parameters, you'll be able to set loader animations to Shiny apps. Furthermore you can select different spinners by looking at this link https://projects.lukehaas.me/css-loaders/.
I used it when I made this app: https://abenedetti.shinyapps.io/bioNPS/
Look at the Species Choropleth map section.
Edit:
Maybe this article and this app could help. Did you had a look at them?

Include library calls in functions?

Is it good practice to include every library I need to execute a function within that function?
For example, my file global.r contains several functions I need for a shiny app. Currently I have all needed packages at the top of the file. When I'm switching projects/copying these functions I have to load the packages/include them in the new code. Otherwise all needed packages are contained in that function. Of course I have to check all functions with a new R session, but I think this could help in the long run.
When I tried to load a package twice it won't load the package again but checks it's already loaded. My main question is if it would slow my functions if I restructure in that way?
I only saw that practice once, library calls inside functions, so I'm not sure.
As one of the commenters suggest, you should avoid loading packages within a function since
The function now has a global effect - as a general rule, this is something to avoid.
There is a very small performance hit.
The first point is the big one. As with most optimisation, only worry about the second point if it's an issue.
Now that we've established the principle, what are the possible solution.
In small projects, I have a file called packages.R that includes all the library calls I need. This is sourced at the top of my analysis script. BTW, all my functions are in a file call func.R. This workflow was stolen/adapted from a previous SO question
If you're only importing a single function, you could use the :: trick, e.g. package::funcA(...) That way you avoid loading the package.
For larger projects, I create an R package that handles all necessary imports. The benefit of creating a package is detailed in this answer on structuring large R projects.

Resources