Closed Captioning Closed captioning available on our YouTube channel

How to boost R Markdown interactivity with runtime Shiny

InfoWorld | May 10, 2019

In this episode of Do More With R, Sharon demonstrates how to turbocharge R Markdown interactions with runtime shiny

Hi. I’m Sharon Machlis at IDG Communications, here with Do More With R: Turbocharge R Markdown interactions with runtime shiny.
R Markdown is one of my favorite things about modern R. It offers an easy way to combine text, R code, and the results of R code in a single document. And when that document is HTML, you can add some user interaction with packages like DT for searchable tables or leaflet for zoomable maps.
But if you want to amp up that doc’s potential for interaction, consider adding “runtime shiny.”
Shiny is a Web application framework for R with a pretty specific format. It requires special sections for the user interface and server logic, and extra code to place each item that’s displayed. Syntax for a Shiny app layout can be daunting for first timers.
What you might not know is: You can turn an R Markdown document into a mini Shiny app without a lot of that rigid structure. It’s a nice way to ease into learning the framework. You can jump right in and experiment with user inputs and results, without worrying about typical newbie problems like nested parentheses and where all the commas go. And even if you’re more experienced with shiny, a shiny document can sometimes make sense if you don’t need a full-blown application. I find it a useful way to test functionality before worrying about layouts.
So let’s get started.
This is a conventional R Markdown document with a table that shows some demographic data by Massachusetts zip code.
The table is searchable, so users can search by zip code, city, and other columns; and they can also sort by a column. I can look at all the zip codes in Middlesex county and then sort for the ones with the highest median household income, or priciest monthly housing, and so on. However, while I can sort the table, the other items don’t change. Same histogram, same text.
It would be nice to have even more information that’s interactive. I’d like the user to be able to select individual cities and see everything on the page change.
That’s where runtime shiny comes in.
I’ll open a copy of the same document and add runtime: shiny to the YAML. Watch the knit icon as I do that. Did you see it change from “Knit” to “Run document”? This is now a mini-shiny application. I’ll also add shiny to the packages I’m loading.
I’ve got another copy of this same document, with a line of code that adds a dropdown list so users can choose one or more cities. selectInput() is the function that creates the dropdown. Let me go over the arguments to selectInput()
The first one, “mycities”, is the variable name that will store whatever the user picks. That second argument is the text that will appear with the dropdown list. The third argument, choices, lists all the possible values in the dropdown list. In this case, I’m taking all the unique city names in my data set, and then sorting them in alphabetical order. Multiple equals true lets users select more than one city. And, finally, selected = Boston defaults to Boston being the selected city. Pretty straightforward so far.
There are a few important points about what happens next. Mycities is no longer a “regular” R variable. It’s dynamic, based on user input. And that means you can’t refer to it as just “mycities” anymore. Instead, it’s now input$mycities.
1. Anything that uses the dynamic input is also dynamic. And that means it can’t be treated like a regular R variable either. You will save a lot of headaches when working with shiny if you remember that.
2. Values – such as a data frame – need to be “reactive.” That’s as easy as wrapping it in a special function, but you need to remember to do it.
3. Anything that displays dynamic content – a table, a map, a histogram, or even text – needs to be rendered in a special way, using one of shiny’s special render functions. The good news is that shiny takes care of most of the functionality of monitoring for changes and calculating results. We just need to remember to use the special functions.
Let me show you what I mean.
I’d like to create a data frame called mydata that filters for any rows where the City one of the cities that the user selects. However, a plain dplyr filter command won’t work.
Do you see the error message? mycities isn’t found, because it’s not a regular R variable. The way shiny works, I need to refer to it as input$mycities.
I’ll change mycities to input$mycities. But I’ll still get an error.
You’ll likely see that error a lot when you start with shiny. It means that you’re trying to create something dynamic the regular R way, Instead, you need to make it reactive.
Fortunately, in this case it’s as simple as using the reactive function.
The mydata object now holds a reactive expression. Now you can see that we’ve got a dropdown list, but it can’t do anything yet. Let’s add a data table.
This code won’t work either, for 2 reasons. First, mydata is a reactive expression, not a typical variable. So I can’t just use mydata to access its value. I need to refer to it almost like it was a regular function: with parentheses after it. This error message is a bit cryptic, but what it says is that mydata isn’t a data frame or matrix. In fact, it’s a reactive expression. So let’s fix that by adding parentheses
Ah, here’s an error message that we’re already familiar with: I’m trying to display something dynamic in a “regular R way.” And that won’t work.
To fix this, I need one of shiny’s render function. A lot of visualization packages have their own special shiny render functions, and DT is one of them. The wrapper function is renderDT. I’ll add that and run the document again. It works!
I can use the same mydata reactive value to create a histogram.
And even a map.
That’s a lot to take in. And if you’re new to shiny, you’ll need some practice – like with any coding skill - before it makes sense. But if you always remember that anything dynamic – values or displays – needs special treatment, that’s a big step forward.
For more details about code used this episode, if you’re watching this as a stand-alone video, check out the accompanying InfoWorld article at the URL on your screen.
A final point about R Markdown shiny documents. Once you add runtime shiny, it’s not an HTML file anymore – it’s a mini application. And that means it needs a Shiny server to run.
Anyone with R, RStudio, and the shiny package has a shiny server on their local system, so it’s easy to share these with fellow R users. You can send them a document. Or you can post it online as a zip or tar file and use the shiny runUrl command.
There are special runGitHub and runGist functions for documents on GitHub.
But chances are, at some point, you’ll want to show your work to non R users. That requires a Shiny server somewhere.
One option is RStudio’s service. It’s free for a few limited public apps, but you’ll need a paid account for anything serious.
You can also build your own Shiny server on a cloud service like AWS or Google Compute Engine. You just need the free open-source version of RStudio’s Shiny server software. There’s a great step-by-step tutorial for doing this on the Digital Ocean cloud service, where you can build and run a small Shiny server for just $5 / month.
That’s it for this episode, thanks for watching! For more R tips, head to the Do More With R page at go dot infoworld dot com slash more with R, all lowercase except for the R. You can also find the Do More With R playlist on the YouTube IDG Tech Talk channel.
Hope to see you next episode!

Featured videos from