Chapter 6 Interactive communication

Last updated: 11 May 2021.

Required reading

Required viewing

Recommended reading

Key concepts/skills/etc

  • Building a website using within the R environment using (in order of ease): postcards, distill, and blogdown.
  • Thinking of about how we can take advantage of interaction in maps, and broadening the data that we make available via interactive maps, while still telling a clear story.

Key libraries

  • blogdown
  • distill
  • leaflet
  • mapdeck
  • postcards
  • tidyverse
  • usethis

Key functions/etc

  • blogdown:::serve_site()
  • distill::create_article()
  • postcards::create_postcard()
  • usethis::use_git()
  • usethis::use_github()

6.1 Making a website

6.1.1 Introduction

A website is a critical part of communication. For instance, it is a place to bring together everything that you’ve done, and it allows you some control of your online presence. You need a website.

One way to make a website is to use the blogdown package (Xie, Dervieux, and Hill 2021). blogdown is a package that allows you to make websites (not just blogs, notwithstanding its name) largely within R Studio. It builds on Hugo, which is a popular tool for making websites. blogdown lets you freely and quickly get a website up-and-running. It is easy to add content from time-to-time. It integrates with R Markdown which lets you easily share your work. And the separation of content and styling allows you to relatively quickly change your website’s design.

However, blogdown is brittle. Because it is so dependent on Hugo, features that work today may not work tomorrow. Also, owners of Hugo templates can update them at any time, without thought to existing users. blogdown is great if you know what you’re doing and have a specific use-case, or style, in mind. However, recently there are two alternatives that are better starting points.

The first is distill (Allaire et al. 2021). Again, this is an R package that wraps around another framework, in this case Distill. However, in contrast to Hugo, Distill is more focused on common needs in data science, and is also only maintained by one group, so it can be a more stable choice. That said, the default distill site is fairly unremarkable. As such, here we recommend a third option.

The third option, and the one that we’ll start with, is postcards (Kross 2021). This is a tailored solution that creates simple biographical websites that look great. If you followed the earlier chapter and set-up GitHub, then you should literally be able to get a postcards website online in five minutes.

6.1.2 Postcards

To get started with postcards, we first need to install the packages.

install.packages('postcards')

You will want to create a new project for your website, so ‘File -> New Project -> New Directory -> Postcards Website.’ You’ll then get a pick a name and location for the project, and you can select a postcards theme. In this case I’ll choose ‘trestles,’ and you probably want to tick ‘Open in new session.’

That will open a new file and you should now click ‘Knit’ to build the site. The result will be a fairly great one-page website (Figure 6.1)!

Example of default Trestles website made with the `postcards` package

Figure 6.1: Example of default Trestles website made with the postcards package

At this point, we should update the basic content to match our own. For instance, here is the same website, but with my details (Figure 6.2).

Example of Trestles website with my own details

Figure 6.2: Example of Trestles website with my own details

When you’ve got the site how you’d like it, then you should add it to GitHub. GitHub will try to build a site, which was don’t want so you need to first add a hidden file by running this in the console:

file.create('.nojekyll')

Then the easiest way (assuming that you set everything up in earlier chapters) is to use the usethis package (Wickham and Bryan 2020).

usethis::use_git()
usethis::use_github()

The project will then be on your GitHub repo and you can use GitHub pages to host it: ‘Settings -> Pages’ and then change the source to ‘main’ or ‘master,’ depending on your settings.

6.1.3 Distill

To get started with distill (Allaire et al. 2021), we are going to build a framework around our postcards site, following Presmanes Hill (2021a) fairly closely (please go to Alison’s blogpost for the details). After that we’ll explore some of the aspects of distill that make it a nice choice, and mention some of the trade-offs that you make if you choose this option. First, we need to install distill.

install.packages('distill')

Again, create a new project for your website, so ‘File -> New Project -> New Directory -> Distill Blog’ (there’s not really much difference between the website and blog options).

You’ll then get a pick a name and location for the project, and you can set a title. Select ‘Configure for GitHub Pages’ and also ‘Open in a new session’ (if you forget to do any of this or change your mind then it’s not a big deal - these can always be changed ex post or you can just delete the directory and start again). It should look something like Figure 6.3.

Example settings for setting up Distill.

Figure 6.3: Example settings for setting up Distill.

At this point you can click ‘Build Website’ in the Build tab, and you’ll see the default website, which should look something like Figure 6.4.

Example of default Distill website.

Figure 6.4: Example of default Distill website.

Again, now we need to do the work to update things. The default for the ‘Distill Blog’ setting is that the blog is the homepage. We can change that. I really liked the bio page from earlier, so we could use that approach.

First change the name of the ‘index.Rmd’ file to ‘blog.Rmd.’ Then create a new ‘trestles’ page:

postcards::create_postcard(file = "index.Rmd", template = "trestles")

The trestles page that you just created will open, and you need to add the following line in the yaml.

site: distill::distill_website

In Figure 6.5 I added it to line 16 and then rebuilt the website.

Updating the yaml to change the homepage.

Figure 6.5: Updating the yaml to change the homepage.

We can make the same changes to the default content as earlier, updating the links, image, and bio. The advantage of using Distill is that we now have additional pages, not just a one-page website, and we also have a blog. By default, we have an ‘about’ page, but some other pages that may be useful, depending on your particular use-case, could include: ‘research,’ ‘teaching,’ ‘talks,’ ‘projects,’ ‘software,’ ‘datasets.’ For now, I’ll talk through adding and editing a page called ‘software.’

We can use the following function:

distill::create_article(file = 'software')

That will create and open an R Markdown document. To add it to the website, open ’_site.yml’ and then add a line to the ‘navbar’ (Figure 6.6(. After this is done then re-building the site will result in that software page having been added.

Adding another page to the website.

Figure 6.6: Adding another page to the website.

Continue with this process until you’re happy with your site. For instance, we may want to add our blog back. To do this follow the same pattern as before, but with ‘blog’ instance of ‘software.’

When you’re ready, you can get your website online in the same way as we did with the postcards site (i.e. push to GitHub and then use GitHub Pages).

Using the distill is a great option if you want a multi-page website, but still want a fairly controlled environment. There are a lot of options that you can change and the best place to start with that is to see Alison Hill’s blog post (Presmanes Hill 2021a), but the distill package homepage is also useful.

That said, distill is very opinionated. Until recently they didn’t even allow a different citation style! While it is a great option (and what I use for my own website), if you want something that is more flexible, then blogdown might be a better option.

6.1.4 Blogdown

Using blogdown (Xie, Dervieux, and Hill 2021) is more work than Google sites or Squarespace. It requires a little more knowledge than using a basic Wordpress site. And if you want to customise absolutely every aspect of your website, or need everything to be ‘just so’ then blogdown may not be for you. Further, blogdown is still under active development and various aspects may break in future releases. However, blogdown allows a variety and level of expression that is not possible with distill.

This post is a simplified version of Presmanes Hill (2021b) and Xie, Thomas, and Presmanes Hill (2021). It sticks to the basics and doesn’t require much decision-making. The purpose is to allow someone without much experience to use blogdown to get a website up-and-running. Head to those two resources once you’ve got a website working and want to dive a bit deeper.

We’ll need to install blogdown.

install.packages("blogdown")

Again, create a new project for your website, so ‘File -> New Project -> New Directory -> Website using blogdown.’ At this point you can set a name and location, and also select ‘Open in a new session.’ It should look something like Figure 6.7.

Example settings for setting up blogdown

Figure 6.7: Example settings for setting up blogdown

You can again click ‘Build Website’ from the ‘Build’ pane, but then an extra step is needed, of serving the site:

blogdown:::serve_site()

The site will show in the ‘Viewer’ pane (Figure 6.8).

Serving default blogdown site.

Figure 6.8: Serving default blogdown site.

At this point, the default website is being ‘served’ locally. This means that changes you make will be reflected in the website that you see in your Viewer pane. To see the website in a web browser, click ‘Show in new window’ button on the top left of the Viewer. That will open the website using the address that the R Studio also tells you.

You probably want to update the ‘About’ section. To do that go to ‘content -> about.md’ and add your own content. One nice aspect of blogdown is that it will automatically re-load the content when you save, so you should see your changes immediately show up.

You may also like to change the logo. You could do this by adding a square image to ‘public/images/’ and then changing the call to ‘logo.png’ in ‘config.yaml.’

When you’re happy with it, you can make your website public in the same way that is described for postcards.

This all said, the biggest advantage of using blogdown is that it allows us to use Hugo templates. This provides a large number of beautifully crafted websites. To pick a theme you can go to the Hugo themes page: https://themes.gohugo.io. There are hundreds of different themes. In general, most of them can be made to work with blogdown, but sometimes it can be a bit of a hassle to get them working.

One that I particularly like is Apéro: https://hugo-apero-docs.netlify.app. If you like that too, then you could use that theme by calling it when you create a new site. As a reminder, ‘File -> New Project -> New Directory -> Website using blogdown.’ At this point, in addition to setting the name and location, you can specify a theme. Specifically, in ‘Hugo theme’ field, you specify the GitHub username and repository, which in this case is ‘hugo-apero/apero’ (Figure 6.9).

Using the Apéro theme.

Figure 6.9: Using the Apéro theme.

6.2 Interactive maps

The nice thing about interactive maps is that you can let your users decide what they are interested in. Additionally, if there is a lot of information then you may like to leave it to your users as to selectively focus on what they are interested in. For instance, in the case of Canadian politics, some people will be interested in Toronto ridings, while others will be interested in Manitoba, etc. But it would be difficult to present a map that focuses on both of those, so an interactive map is a great option for allowing users to zoom in on what they want.

6.2.0.1 Leaflet

The leaflet package is originally a JavaScript library of the same name that has been brought over to R. It makes it easy to make interactive maps. The basics are fairly similar to the ggmap set-up, but of course after that, there are many, many, options.

Let’s redo the bike map from earlier, and possibly the interaction will allow us to see what the issue is with the data.

In the same way as a graph in ggplot begins with the ggplot() function, a map in the leaflet package begins with a call to the leaflet() function. This allows you to specify data, and a bunch of other options such as width and height. After this, we add ‘layers,’ in the same way that we added them in ggplot. The first layer that we’ll add is a tile with the function addTiles(). In this case, the default is from OpenStreeMap. After that we’ll add markers that show the location of each bike parking spot with addMarkers().

library(leaflet)
library(tidyverse)

bike_data <- read_csv("outputs/data/bikes.csv")

leaflet(data = bike_data) %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addMarkers(lng = bike_data$longitude, 
             lat = bike_data$latitude, 
             popup = bike_data$street_address,
             label = ~as.character(bike_data$number_of_spots))

There are two options here that may not be familiar. The first is popup, and this is what happens when you click on the marker. In this example this is giving the address. The second is label, which is what happens when you hover over the marker. In this example it is given the number of spots.

6.2.0.2 COVID-19

Let’s have another go, this time with Ontario data on COVID-19.

We can download the latest data from the Ontario Data Catalogue. This is a fast moving situation in which they are likely to make breaking changes to this dataset. To ensure this book works, I will save and then use the dataset as at 4 April 2020, but you are able to get the up-to-date dataset using the link and the code.

ontario_covid <- read_csv("https://data.ontario.ca/datastore/dump/455fd63b-603d-4608-8216-7d8647f43350?bom=True")
write_csv(ontario_covid, "inputs/data/ontario_covid_2020-04-04.csv")
ontario_covid <- read_csv("inputs/data/ontario_covid_2020-04-04.csv")
head(ontario_covid)
## # A tibble: 6 x 14
##   `_id` ROW_ID ACCURATE_EPISODE_DATE Age_Group CLIENT_GENDER CASE_ACQUISITIONIN…
##   <dbl>  <dbl> <dttm>                <chr>     <chr>         <chr>              
## 1     1      1 2020-03-07 00:00:00   40s       MALE          Neither            
## 2     2      2 2020-03-08 00:00:00   20s       MALE          Neither            
## 3     3      3 2020-03-10 00:00:00   40s       FEMALE        Neither            
## 4     4      4 2020-03-11 00:00:00   50s       FEMALE        Neither            
## 5     5      5 2020-03-12 00:00:00   30s       FEMALE        Neither            
## 6     6      6 2020-03-15 00:00:00   50s       MALE          Neither            
## # … with 8 more variables: OUTCOME1 <chr>, Reporting_PHU <chr>,
## #   Reporting_PHU_Address <chr>, Reporting_PHU_City <chr>,
## #   Reporting_PHU_Postal_Code <chr>, Reporting_PHU_Website <chr>,
## #   Reporting_PHU_Latitude <dbl>, Reporting_PHU_Longitude <dbl>

There is a lot of information here, but we’ll just plot the number of cases, by the reporting area (health areas). So this isn’t the location of the person, but the location of the responsible health unit. Because of this, we’ll add a little bit of noise so that the marker for each person can be seen. We do this with jitter().

ontario_covid <- 
  ontario_covid %>% 
  mutate(Reporting_PHU_Latitude = jitter(Reporting_PHU_Latitude, amount = 0.1),
         Reporting_PHU_Longitude = jitter(Reporting_PHU_Longitude, amount = 0.1))

We will introduce a different type of marker here, which is circles. This will allow us to use different colours for the outcomes of each case. There are three possible outcomes: the case is resolved, it is not resolved, or it was fatal.

library(leaflet)

pal <- colorFactor("Dark2", domain = ontario_covid$OUTCOME1 %>% unique())

leaflet() %>%
  addTiles() %>%  # Add default OpenStreetMap map tiles
  addCircleMarkers(
    data = ontario_covid,
    lng = ontario_covid$Reporting_PHU_Longitude, 
    lat = ontario_covid$Reporting_PHU_Latitude, 
    color = pal(ontario_covid$OUTCOME1),
    popup = paste("<b>Age-group:</b>", as.character(ontario_covid$Age_Group), "<br>",
                  "<b>Gender:</b>", as.character(ontario_covid$CLIENT_GENDER), "<br>",
                  "<b>Acquisition:</b>", as.character(ontario_covid$CASE_ACQUISITIONINFO), "<br>",
                  "<b>Episode date:</b>", as.character(ontario_covid$ACCURATE_EPISODE_DATE), "<br>")
    ) %>% 
  addLegend("bottomright", 
            pal = pal, 
            values = ontario_covid$OUTCOME1 %>% unique(),
    title = "Case outcome",
    opacity = 1
  )

6.2.0.3 mapdeck

Thank you to Shaun Ratcliff for introducing me to mapdeck.

The package mapdeck is an R package that is built on top of Mapbox (https://www.mapbox.com). It is based on WebGL, which means that your web browser does a lot of work for you. The nice thing is that because of this, it can do a bunch of things that leaflet struggles with, especially dealing with larger datasets. Mapbox is a full-featured application that many businesses that you may have heard of use: https://www.mapbox.com/showcase. To close out this discussion of mapping, I want to briefly touch on mapdeck, as it is a newer, but very exciting, package.

To this point we have used stamen maps as our tile, but mapdeck uses mapbox - https://www.mapbox.com/ - and so you need to register and get a token for this. (It’s free.) Once you have that token you add it to R using:

library(mapdeck)
set_token("asdf") # replace asdf with your token.
mapdeck_tokens()

set_token(test$key)

(Don’t add it into your script otherwise everyone will be able to take it and use it, especially once you add it to GitHub.)

Then we need some data. Here we’re going to just use the example dataset, which is about flights.

# Code taken from the example: https://github.com/SymbolixAU/mapdeck
library(mapdeck)

url <- 'https://raw.githubusercontent.com/plotly/datasets/master/2011_february_aa_flight_paths.csv'
flights <- read.csv(url)
flights$info <- paste0("<b>",flights$airport1, " - ", flights$airport2, "</b>")

head(flights)
##   start_lat start_lon  end_lat    end_lon airline airport1 airport2 cnt
## 1  32.89595 -97.03720 35.04022 -106.60919      AA      DFW      ABQ 444
## 2  41.97960 -87.90446 30.19453  -97.66987      AA      ORD      AUS 166
## 3  32.89595 -97.03720 41.93887  -72.68323      AA      DFW      BDL 162
## 4  18.43942 -66.00183 41.93887  -72.68323      AA      SJU      BDL  56
## 5  32.89595 -97.03720 33.56294  -86.75355      AA      DFW      BHM 168
## 6  25.79325 -80.29056 36.12448  -86.67818      AA      MIA      BNA  56
##               info
## 1 <b>DFW - ABQ</b>
## 2 <b>ORD - AUS</b>
## 3 <b>DFW - BDL</b>
## 4 <b>SJU - BDL</b>
## 5 <b>DFW - BHM</b>
## 6 <b>MIA - BNA</b>

Finally, we can call the map. Again, this is just the example in the package’s website.

mapdeck(style = mapdeck_style('dark')
        ) %>%
  add_arc(
    data = flights
    , origin = c("start_lon", "start_lat")
    , destination = c("end_lon", "end_lat")
    , stroke_from = "airport1"
    , stroke_to = "airport2"
    , tooltip = "info"
    , layer_id = 'arclayer'
  )

And this is pretty nice!

6.3 Shiny

Shiny is a way of making interactive web applications (not just maps) using R. It’s fun, but fiddly. Here we’re going to step through one way to take advantage of Shiny, and that’s to quickly build a survey.