A totally different, read-me-first Shiny tutorial

Shiny is the package for adding a web interface to the R statistical language. The Shiny team provides a tutorial, articles, examples, a reference guide, a question and answer forum, conference videos from 2016 and 2017, and a GitHub repository.

It’s a lot and sometimes things get a little blurry. This week I’m going to write a read-me-first tutorial about learning Shiny based on my experiences working and playing with it over the last year or so.

First, although you write Shiny code using  R, the way the programs work is nothing like R. With R you write code that starts at the beginning and runs to the end. With Shiny you write code snippets or “recipes” that run when they are buzzed, in an order you should consider totally random.

Buzzers (my language, not Shiny’s) are pressed by users interacting with the web interface. All the inputs on a web page are buzzers. So, for example, when the user types a single character in a text field, or clicks a radio button, or goes to a new tab on the screen, a buzzer will buzz. You can also set up special web-interface buzzers. For example, you can define a buzzer that buzzes when your user drags the cursor over part of a plot and that provides you with those coordinates (so you can, for example, zoom into that section of the plot). Beyond that, it’s possible to create variables and functions in your own code that are buzzers. These code buzzers buzz when the value they return changes.

As the programmer, you write code that responds to the smallest subset of the available buzzers as possible. If you don’t write code that responds to a specific buzzer, that user interaction is ignored. And, believe me, Shiny programs can safely ignore most of the buzzes. (Do you really need to know every time the user types a single character? If you’re trying to recreate the way that the Google search box guesses what you’re typing, it’s a magnificent capability, but most of the time it’s just too much).

Let’s use the word butlers for these code recipes that respond to buzzers. In Shiny language, the butlers and some of the buzzers tend to be called “reactives,” just so you know. There are three kinds of butlers: render… functions, “reactive expressions”, and observers.

Shiny’s set of render… functions are used to display text, tables, images, and plots on the web page. If you use a buzzer inside a render… function, that function will run every time that particular buzzer buzzes. If the function takes more than a moment to run – rendering a plot for example – you definitely don’t want it running every time something buzzes.

I put “reactive expressions” in quotes because, in English, all three types of butlers could be called that. But here we refer to a specific type, which is a function that is both a buzzer and a butler. It’s a butler because it will run every time a buzzer in its code buzzes. It’s a buzzer because any other function that calls it will run whenever the value returned by this kind of function changes. What it means to have something that is a buzzer and a butler and a function is one of the more difficult concepts to understand when learning Shiny. To help keep everything straight, let’s call these buzzer-butler functions.

Finally, there are observers. Unlike buzzer-butler functions, observers are butlers but not buzzers. Unlike both buzzer-butler and render… functions, observers don’t return a value. They are meant to control side-effects, such as a button that downloads a file.

So there are three kinds of butlers. There are also three kinds of buzzers. We’ve already talked about two of them: inputs on the web page and buzzer-butler functions. The third one Shiny calls a “reactive variable,” but think of it as a buzzer variable. It’s simply a variable you can use as a buzzer. Every time your code changes the value of a buzzer variable, every other function in your code that uses that buzzer variable runs.

The Shiny docs sometimes talk about “dependency.” This just means that Shiny has established a relationship between a butler and buzzer. Both butlers and buzzers are polygamous. A particular buzzer can be used to wake up multiple butlers; a particular butler can be shaken awake by any one of a set of buzzers.

Sometimes a section of code needs to get the current value of a buzzer, but you don’t want that particular piece of code to execute every time the buzzer buzzes. For example, while drawing a plot, you might want to get the user-desired plot title from a text input, but you don’t want to redraw the plot every time the user enters a character in that input field. One way to control this is to embed the buzzer inside an isolate(buzzer) function.

In my own coding, more often than not, I want all the buzzers isolated. Shiny provides two nice functions for this. One is a buzzer-butler function called eventReactive(buzzer, { code }) and the other is an observer called observeEvent(buzzer, { code }). These two types of functions run when the designated buzzer buzzes, but any other buzzers that appear in the code section are automatically isolated.

In my own coding style, the observeEvent() function has become a primary workhorse – mostly because it’s relatively easy to understand what it actually does. More on that coming up, but first, let’s get some practice with buzzers and butlers.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.