Some notes on my first shiny app
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Since there are plenty of examples out there telling you how to get started with shiny (like Rstudio’s, or Google), I will focus on telling some of the stuff that I did learned and may not be obvious at first, including some of the mistakes I made.
Before start, I just want to stress that I’m writing this after my first shiny app, you’ve been warned! Here it goes:
Use the “two-file” method Instead of putting everything, UI and Server, in a single
app.R
file, create two separate filesserver.R
andui.R
(see here). This is not hard to figure out, but is not the first thing that you see when you create a shiny app from Rstudio. The reason why is very simple, as your project grows, you want to have it organized using several Rscripts rather than a single big R file that’s calledapp.R
. That’s OK but not very friendly to maintain. This takes us to the next point.Use separate R files for more complex functions If you have other functions that you would like to run with your app, either use the
global.R
script, which will be run automatically, or just source your file likesource("extra-functions.R")
(see here). Again, this makes code maintenance easier.Make sure all the packages that you need are installed You can either keep the source version of such packages as a sub directory, or follow a more simple approach such as using
require
, e.g.:if (!require(somepackage)) { install.packages("somepackage") library(somepackage) }
This is especially important when deploying shiny in a in-house server as the “shiny user” has to have access to those R packages. You can always try to install them globally too so that all users in the server have access to the required packages.
More important, make sure that you have
shiny
andrmarkdown
installed and available system-wide! I spent roughly half an hour figuring out why my shiny apps didn’t started once I started the server in our machine.Nested apps If you want to include several apps under the same folder in your
/srv/shiny-server
folder (which is where the shiny apps live), e.g.my-apps
, avoid includingR
orRmd
files in that folder, shiny will try to run those as shiny apps and, for some reason that I’m not aware of, links that go from html pages in that folder to your sub directory apps will not work.For example, suppose that we have two apps,
shinyApp1
andshinyApp2
and we want to keep those in the same folderyour-site
, and you have a nice front-end website allowing you to access to such apps with relative links in the form of<a href="shinyApp1">Go to shinyApp1</a>
, you’ll just need to include theindex.html
of your website (which you can create withrmarkdown
). The following would be wrong:+---/srv/shiny-server | +---/you-site | +---index.html | +---index.Rmd # THIS SHOULDN'T BE HERE! | +---shinyApp1 | +---server.R | +---ui.R | +---shinyApp2 | +---server.R | +---ui.R
This would result in having a broken link in your
index.html
file. You should do this instead, remove the Rmd file from theyour-site
folder:+---/srv/shiny-server | +---/you-site | +---index.html | +---shinyApp1 | +---server.R | +---ui.R | +---shinyApp2 | +---server.R | +---ui.R
This example was adapted from Section 2.7.1 from the Shiny’s Admin guide.
Read about Reactivity This is a fundamental thing to understand in Shiny, moreover, the key function to review is
reactive
, which allows you to create intermediate points (reactive conductors) between your input and output data in the shiny app. Just to give you an idea, here is an (adapted) example that I find useful from the shiny documentation:This will work
# A function that will be called from within the server fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2)) server <- function(input, output) { # Calling your fancy fib function, notice the # # reactive({ ... }) # # wrapper. currentFib <- reactive({ fib(as.numeric(input$n)) }) # You use it as a function later on. output$nthValue <- renderText({ currentFib() }) output$nthValueInv <- renderText({ 1 / currentFib() }) }
This won’t work, since currentFib is not in the “reactive” world!
server <- function(input, output) { # Will give error currentFib <- fib(as.numeric(input$n)) output$nthValue <- renderText({ currentFib }) }
For my next steps, I expect to be able to include a shiny app in the R packages aphylo
(which is not on CRAN yet, but available here) and rgexf
(which it is on CRAN, but is currently on a major update here)
I recommend taking a look at this section from the bookdown that talks about how to include shiny apps within web pages.
Finally, if you are interested, you can take a look at the shiny app here and at the code here
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.