7  Interactive communication

Required material

Key concepts and skills

Key packages and functions

7.1 Introduction

Books and papers have been the primary mediums for communication for thousands of years. But with the rise of computers, and especially the internet, in recent decades, these static approaches have been complemented with interactive approaches. Fundamentally, the internet is about making files available others. If we additionally allow them to do something with what we make available, then we need to take a variety of additional aspects into consideration.

In this chapter we begin by covering how to create and publish a website. This serves as a place to host a portfolio of work. After that we cover adding interaction to maps and graphs, which are two that nicely lend themselves to this.

7.2 Making a website

A website is a critical part of communication. For instance, it is a place to make a portfolio of work publicly available. One way to make a website is to use Quarto’s built in websites. Another is to use blogdown (Xie, Dervieux, and Presmanes Hill 2021). blogdown is a package that allows you to make websites, not just blogs (notwithstanding its name), largely within RStudio. It builds on “Hugo”, which is a popular general framework for making websites. blogdown enables us to freely and quickly get a website up-and-running. It is easy to add content from time-to-time. And it integrates with RStudio, which makes it easy to share work. But 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 a good option if we know what we are doing, or have a specific use-case, or style, in mind. But other alternatives 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”. But in contrast to Hugo, Distill is more focused on common needs in data science, and is also only maintained by one group, so it may be considered a more stable choice. That said, the default distill site is a little plain looking, and there may be concerns about maintenance of it moving forward. As such, following Presmanes Hill (2021a), we will pair it with a third option, postcards (Kross 2021). This is a tailored solution that creates simple biographical websites that look great. Having set-up GitHub in RStudio, it is literally possible to have a postcards website online in five minutes.

7.2.1 Postcards

Begin by installing postcards, with install.packages("postcards") and then creating a new project for the website (“File” -> “New Project” -> “New Directory” -> “Postcards Website”). We can then pick a name and location for the project, and select a postcards theme. In this case, we can start with “trestles” but this can be changed later. Click the option to “Open in new session” and then create the project.

That will open a new file and we can now build the site by clicking “Knit”. This will result in a one-page website (Figure 7.1).

Figure 7.1: Example of a website made with postcards using the “trestles” theme

We can now update the basic content such as name, bio, and links to match our own (Figure 7.2).

Figure 7.2: Example of Trestles website with updated details

After the details are personalized, we can push it to GitHub which will act as a host for our website. By default, GitHub would try to build the site, which we do not want, so we need to first add a hidden file to turn that off, by running this in the console:


Then, assuming GitHub was set-up in Chapter 4, we can use usethis (Wickham and Bryan 2020) to get our newly created project onto GitHub. We use use_git() to initialize a Git repository, and then use_github() pushes it to GitHub.


The project will then be on GitHub. We can use GitHub pages to host it: “Settings -> Pages” and then change the source to “main” or “master”, depending on your settings. GitHub will let you know the address that you can share to visit your site.

7.2.2 Quarto

We will now use Quarto to build a basic website. The advantage of a Quarto website over using postcards is that it enables us to have a multi-page website, rather than just a single-page website.

First, create a new project (“File” -> “New project” -> “New Directory” -> “Quarto Website” -> give it a name, and select “Open in new session” -> “Create Project” (Figure 7.3).

Figure 7.3: Example settings for setting up a Quarto website

By default a basic website is included and this can be produced with “Build” -> “Render Website” (Figure 7.4). By default it will show in the “Viewer” pane, but can also be shown in a New Window.

Figure 7.4: Building a Quarto website

Again, at this point we may like to change the details to reflect our own. In particular, we may like to change the title of “index.qmd”, and add our own details (Figure 7.5).

Figure 7.5: Personalizing the Quarto website

Content that is included in the primary menu is specified in “_quarto.yml”. We could add another page to this, such as “contact.qmd” and to create the content that would be included we may like to duplicate, say, “about.qmd” and then edit that (Figure 7.6).

Figure 7.6: Updating the Quarto yaml

From here it can be pushed to GitHub and then host it with GitHub Pages in the same way as with the postcards website.

7.2.3 Distill

We will now use distill (Allaire et al. 2021) to build additional infrastructure around our postcards site, following Presmanes Hill (2021a). After that we will explore some of the aspects of distill that make it a nice choice, and mention some of the trade-offs. First, we install distill with install.packages("distill"), and again, create a new project for the website (“File” -> “New Project” -> “New Directory” -> “Distill Blog”). There is not much difference between “Distill Blog” and “Distill Website”. When using “Distill Blog” we can distinguish between pages in the navbar and posts in the “_posts” folder, which is what is added to the blog page of the website. But both ultimately produce a website. We will use “Distill Blog” just so that there is also a blog page.

We can then pick a name and location for the project, and set a title. Select “Configure for GitHub Pages” and also “Open in a new session”. These options can be changed ex post. It should look something like Figure 7.7.

Figure 7.7: Example settings for setting up distill

At this point we can click “Build Website” in the Build tab, and we should see the default website (Figure 7.8).

Figure 7.8: Example of default distill website

Again, now we need to update it to reflect our own details. The default for a “Distill Blog” is that the blog is the homepage. We can change that to use a postcards page as the homepage. First we change the name of “index.Rmd” to “blog.Rmd” and then create a new “trestles” page:

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

The “trestles” page will be created as “index.Rmd” and it will open. We need to add the following line to the file “index.Rmd”: site: distill::distill_website. In Figure 7.9 it was added at line 15, and then we can rebuild.

Figure 7.9: Updating the yaml to change the homepage

We can make the same changes to the default content as earlier, for instance, 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 the particular use-case, include: “research”, “teaching”, “talks”, “projects”, “software”, and “datasets”. As an example, we will add and edit a page called “software” using 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 7.10). After this is done then we can rebuild the website, and the “software” page will have been added.

Figure 7.10: Adding another page to the website

We can continue with this process until we are happy with the website. For instance, we may want to add a blog. To do this we follow the same pattern as before, but with “blog” instead of “software”.

When we are happy with our website, we can push it to GitHub and then use GitHub Pages to host it, in the same way that we did with the postcards site.

Using distill is a good option when we need a multi-page website, but still want a fairly controlled environment. There are many options that can be changed, and Presmanes Hill (2021a) is a good starting point, in addition to the distill homepage.

That said, distill is opinionated. While it is a great option, if we want something a little more flexible then blogdown might be a better option.

7.2.4 Blogdown

Using blogdown (Xie, Dervieux, and Presmanes Hill 2021) is more work than Google sites or Squarespace. It requires a little more knowledge than using a basic Wordpress site. And if we need to customize absolutely every aspect of the website, or need everything to be “just so” then blogdown may not be a good option. But blogdown allows a variety and level of expression that is not possible with distill. Presmanes Hill (2021b) and Xie, Thomas, and Presmanes Hill (2021) are useful for learning more about blogdown.

First we need to install blogdown with install.packages("blogdown"). And then we create a new project for the website (“File” -> “New Project” -> “New Directory” -> “Website using blogdown”). At this point we can set a name and location, and also select “Open in a new session” (Figure 7.11).

Figure 7.11: Example settings for setting up blogdown

We can click “Build Website” from the “Build” pane, but then an extra step is needed; we need to serve the site by running blogdown::serve_site(). After this, the site will show in the “Viewer” pane (Figure 7.12).

Figure 7.12: Serving default blogdown site

The default website is now being “served” locally. This means that changes we make will be reflected in the website that we see in the Viewer pane. To see the website in a web browser, click “Show in new window” on the top left of the Viewer. That will open a local preview the website using the address that RStudio also provides.

We now want to update the content, starting with the “About” section. To do that we go to “content/about.md” and modify or add content. One nice aspect of blogdown is that it will automatically reload the content when we save, and so changes should appear immediately. We could modify other aspects also. For instance, we could change the logo, by adding a square image to “public/images” and then changing the call to corresponding image name in “config.yaml”. When we are happy with it, we can make our website public in the same way as we did for postcards.

One 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 we go to the Hugo themes page. 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.

One nice option is Apéro. We can specify the use of this theme as part of creating a new site. At this point, in addition to setting the name and location, we can specify a theme. Specifically, in the “Hugo theme” field, we can specify a GitHub username and repository, which in this case is “hugo-apero/apero” (Figure 7.13).

Figure 7.13: Using the Apéro theme

The result is the default Apéro website to which we could add our own details (Figure 7.14).

Figure 7.14: Example of the Apéro theme

7.3 Interactive maps

The nice thing about interactive maps is that we can let our user decide what they are interested in. For instance, in the case of a map, some people will be interested in, say, Toronto, while others will be interested in Chennai or even Auckland. But it would be difficult to present a map that focused on all of those, so an interactive map is a way to allow users to focus on what they want.

That said, it is important to be cognizant of what we are doing when we build maps, and more broadly, what is being done at scale to enable us to be able to build our own maps. For instance, with regard to Google, McQuire (2019) says:

Google began life in 1998 as a company famously dedicated to organising the vast amounts of data on the Internet. But over the last two decades its ambitions have changed in a crucial way. Extracting data such as words and numbers from the physical world is now merely a stepping-stone towards apprehending and organizing the physical world as data. Perhaps this shift is not surprising at a moment when it has become possible to comprehend human identity as a form of (genetic) ‘code’. However, apprehending and organizing the world as data under current settings is likely to take us well beyond Heidegger’s ‘standing reserve’ in which modern technology enframed ‘nature’ as productive resource. In the 21st century, it is the stuff of human life itself—from genetics to bodily appearances, mobility, gestures, speech, and behaviour—that is being progressively rendered as productive resource that can not only be harvested continuously but subject to modulation over time.

Does this mean that we should not use or build interactive maps? Of course not. But it is important to be aware of the fact that this is a frontier, and the boundaries of appropriate use are still being determined. Indeed, the literal boundaries of the maps themselves are being consistently determined and updated. The move to digital maps, compared with physical printed maps, means that it is possible for different users to be presented with different realities. For instance, “…Google routinely takes sides in border disputes. Take, for instance, the representation of the border between Ukraine and Russia. In Russia, the Crimean Peninsula is represented with a hard-line border as Russian-controlled, whereas Ukrainians and others see a dotted-line border. The strategically important peninsula is claimed by both nations and was violently seized by Russia in 2014, one of many skirmishes over control” (Bensinger 2020).

7.3.1 Leaflet

We can use leaflet (Cheng, Karambelkar, and Xie 2021) to make interactive maps. The essentials are similar to ggmap (Kahle and Wickham 2013), but there are many additional aspects beyond that. We can redo the US military deployments map from Chapter 6 that used troopdata (Flynn 2021). The advantage with an interactive map is that we can plot all the bases and allow the user to focus on which area they want, in comparison with Chapter 6 where we just picked a few particular countries. A great example of why this might be useful is provided by The Economist (2022b) where they are able to show 2022 French Presidential results for the entire country by commune.

In the same way as a graph in ggplot2 begins with ggplot(), a map in leaflet begins with leaflet(). Here we can specify data, and other options such as width and height. After this, we add “layers” in the same way that we added them in ggplot2. The first layer that we add is a tile, using addTiles(). In this case, the default is from OpenStreeMap. After that we add markers with addMarkers() to show the location of each base (Figure 7.15).


bases <- get_basedata()

# Some of the bases include unexpected characters which we need to address
Encoding(bases$basename) <- "latin1"

leaflet(data = bases) |>
  addTiles() |> # Add default OpenStreetMap map tiles
    lng = bases$lon,
    lat = bases$lat,
    popup = bases$basename,
    label = bases$countryname

Figure 7.15: Interactive map of US bases

There are two new arguments, compared with ggmap. The first is “popup”, which is the behavior that occurs when the user clicks on the marker. In this case, the name of the base is provided. The second is “label”, which is what happens when the user hovers on the marker. In this case it is the name of the country.

We can try another example, this time of the amount spent building those bases. We will introduce a different type of marker here, which is circles. This will allow us to use different colors for the outcomes of each type. There are four possible outcomes: “More than $100,000,000”, “More than $10,000,000”, “More than $1,000,000”, “$1,000,000 or less” (Figure 7.16).

build <-
  get_builddata(startyear = 2008, endyear = 2019) |>
  filter(!is.na(lon)) |>
    cost = case_when(
      spend_construction > 100000 ~ "More than $100,000,000",
      spend_construction > 10000 ~ "More than $10,000,000",
      spend_construction > 1000 ~ "More than $1,000,000",
      TRUE ~ "$1,000,000 or less"

pal <-
  colorFactor("Dark2", domain = build$cost |> unique())

leaflet() |>
  addTiles() |> # Add default OpenStreetMap map tiles
    data = build,
    lng = build$lon,
    lat = build$lat,
    color = pal(build$cost),
    popup = paste(
  ) |>
    pal = pal,
    values = build$cost |> unique(),
    title = "Type",
    opacity = 1

Figure 7.16: Interactive map of US bases with colored circules to indicate spend

7.3.2 Mapdeck

mapdeck (Cooley 2020) is based on WebGL. This means the web browser will do a lot of work for us. This enables us to accomplish things with mapdeck that leaflet struggles with, such as larger datasets.

To this point we have used “stamen maps” as our underlying tile, but mapdeck uses Mapbox. This requires registering an account and obtaining a token. This is free and only needs to be done once. Once we have that token we add it to our R environment (the details of this process are covered in Chapter 9) by running usethis::edit_r_environ(), which will open a text file, which is where we should add our Mapbox secret token.


We then save this “.Renviron” file, and restart R (“Session” -> “Restart R”).

Having obtained a token, we can create a plot of our base spend data from earlier (Figure 7.17).


mapdeck(style = mapdeck_style("light")) |>
    data = build,
    lat = "lat",
    lon = "lon",
    layer_id = "scatter_layer",
    radius = 10,
    radius_min_pixels = 5,
    radius_max_pixels = 100,
    tooltip = "location"

Figure 7.17: Interactive map of US bases using Mapdeck

7.4 Shiny

shiny (Chang et al. 2021) is a way of making interactive web applications using R. It is fun, but can be a little fiddly. Here we are going to step through one way to take advantage of shiny, which is to quickly add some interactivity to our graphs. This sounds like a small thing, but a great example of why it is so powerful is provided by The Economist (2022a) where they show how their forecasts of the 2022 French Presidential Election changed over time. We will return to shiny in Chapter 14.

We are going to make an interactive graph based on the “babynames” dataset from babynames (Wickham 2019). First, we will build a static version (Figure 7.18).


top_five_names_by_year <-
  babynames |>
  group_by(year, sex) |>
  arrange(desc(n)) |>
  slice_head(n = 5)

top_five_names_by_year |>
  ggplot(aes(x = n, fill = sex)) +
  geom_histogram(position = "dodge") +
  theme_minimal() +
  scale_fill_brewer(palette = "Set1") +
    x = "Babies with that name",
    y = "Occurances",
    fill = "Sex"

Figure 7.18: Popular baby names

One thing that we might be interested in is how the effect of the “bins” parameter shapes what we see. We might like to use interactivity to explore different values.

To get started, create a new shiny app (“File” -> “New File” -> “Shiny Web App”). Give it a name, such as “not_my_first_shiny” and then leave all the other options as the default. A new file “app.R” will open and we click “Run app” to see what it looks like.

Now replace the content in that file, “app.R”, with the content below, and then again click “Run app”.


# Define UI for application that draws a histogram
ui <- fluidPage(
  # Application title
  titlePanel("Count of names for five most popular names each year."),

  # Sidebar with a slider input for number of bins
        inputId = "number_of_bins",
        label = "Number of bins:",
        min = 1,
        max = 50,
        value = 30

    # Show a plot of the generated distribution

# Define server logic required to draw a histogram
server <- function(input, output) {
  output$distPlot <- renderPlot({
    # Draw the histogram with the specified number of bins
    top_five_names_by_year |>
      ggplot(aes(x = n, fill = sex)) +
      geom_histogram(position = "dodge", bins = input$number_of_bins) +
      theme_minimal() +
      scale_fill_brewer(palette = "Set1") +
        x = "Babies with that name",
        y = "Occurances",
        fill = "Sex"

# Run the application
shinyApp(ui = ui, server = server)

We have just build an interactive graph where the number of bins can be changed. It should look like Figure 7.19.

Figure 7.19: Example of Shiny app where the user controls the number of bins

7.5 Exercises and tutorial


  1. (Plan) Consider the following scenario: Everyday a baby wakes at one of: 4am, 5am, or 6am, and wakes up a parent who has a choice of whether to have coffee or tea. Imagine you have daily data for a year about the time the baby wakes up and which drink the parent had. Please sketch what that dataset could look like and then sketch a graph that you could build to show all observations.
  2. (Simulate) Please further consider the scenario described and simulate the situation where each of the two variables are independent. After that, please simulate another situation where there is some relationship, of your choice, between the time the baby wakes up, and the choice of drink.
  3. (Acquire) Please describe a possible source of such a dataset.
  4. (Explore) Please use shiny to build an interactive version of the graph that you sketched.
  5. (Communicate) Please write two paragraphs about what you did.
  6. Based on Presmanes Hill (2021a), are posts in distill re-built automatically (pick one)?
    1. No
    2. Yes
    3. Depends on settings
  7. Based on Lovelace, Nowosad, and Muenchow (2019), please explain in a paragraph or two, what is the difference between vector data and raster data in the context of geographic data?
  8. Based on Wickham (2021), shiny uses:
    1. Object-oriented programming
    2. Functional programming
    3. Reactive programming
  9. In a paragraph or two, why is it important to have a website?
  10. Which of the following are packages that we could use to make a website (select all that apply)?
    1. distill
    2. blogdown
    3. postcards
    4. hugo
  11. Looking at the help file for postcards, which of the following are themes that we could use (select all that apply)?
    1. jolla
    2. jolla-blue
    3. jolla-red
    4. trestles
    5. mjolnir
    6. onofre
    7. solana
  12. Which function should we use to stop GitHub itself from trying to build our site instead of just serving it (pick one)?
    1. file.create(".nojekyll")
    2. file.remove(".nojekyll")
    3. file.create(".jekyll")
    4. file.remove(".jekyll")
  13. Which argument to addMarkers() is used to specify the behavior that occurs after a marker is clicked (pick one)?
    1. layerId
    2. icon
    3. popup
    4. label


Please obtain data on the ethnic origins and number of Holocaust victims killed at Auschwitz concentration camp. Then use shiny to create an interactive graph and an interactive table. These should show the number of people murdered by nationality/category and should allow the user to specify the groups they are interested in seeing data for. Publish them. Then, based on the themes brought up in Bouie (2022), discuss your work in at least two pages. Submit a PDF created using Quarto, and ensure that it contains a link to your app and the GitHub repo that contains all code and data.


At about this point, Paper Two, in Appendix C, would be appropriate.