forked from RohanAlexander/tswd
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path24-interaction.qmd
More file actions
467 lines (314 loc) · 28.7 KB
/
Copy path24-interaction.qmd
File metadata and controls
467 lines (314 loc) · 28.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
---
engine: knitr
---
# Interaction {#sec-interactive-communication}
**Under construction**
**TODO**
- Add the plotly section
**Prerequisites**
- Read *Geocomputation with R*, Chapter 2 "Geographic data in R", [@lovelace2019geocomputation]
- This chapter provides an overview of mapping in `R`.
- Read *Mastering Shiny*, Chapter 1 "Your first Shiny app", [@wickham2021mastering]
- This chapter provides a self-contained example of a Shiny app.
- Read *We Still Can't See American Slavery for What It Was*, [@americaslavery]
- The article discusses slavery in the US, with a focus on data.
**Key concepts and skills**
- Interactive communication, such as websites, interactive maps, and shiny applications add another dimension to the story we tell. Partly this is just because they allow the user to focus on what they are interested in, but it it also just nice to be able to consider movement.
- A key aspect of communication and presence is having a website and we focus on using a Quarto document to do this.
- Once we have a website, then we can create interactive maps, using `leaflet` [@ChengKarambelkarXie2017] and `mapdeck` [@citemapdeck].
- And interactive shiny apps allow us to easily add interaction to graphs, using `Shiny` [@citeshiny].
**Software and packages**
- `babynames` [@citebabynames]
- `leaflet` [@ChengKarambelkarXie2017]
- `mapdeck` [@citemapdeck]
- `shiny` [@citeshiny]
- `tidyverse` [@tidyverse]
- `troopdata` [@troopdata]
- `usethis` [@usethis]
```{r}
#| message: false
#| warning: false
library(babynames)
library(leaflet)
library(mapdeck)
library(shiny)
library(tidyverse)
library(troopdata)
library(usethis)
```
## 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. Interactive communication is also important as models become more complex. For instance, @daSilva2023 develop interactive graphics which they use to better understand their random forest models.
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.
## Quarto websites
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` [@citeblogdown]. `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` [@citedistill]. 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 @hillpostcards, we will pair it with a third option, `postcards` [@citepostcards]. This is a tailored solution that creates simple biographical websites that look great. -->
Having set-up GitHub in RStudio, it is possible to have a website online in five minutes.
<!-- ### 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 (@fig-trestles). -->
<!-- {#fig-trestles width=90% fig-align="center"} -->
<!-- We can now update the basic content such as name, bio, and links to match our own (@fig-trestlesredux). -->
<!-- {#fig-trestlesredux width=90% fig-align="center"} -->
One nice feature of a Quarto website is that it enables us to have a multi-page, rather than single-page, website. As it is fundamentally a Quarto document, it also allows us to use the skills that we developed in @sec-reproducible-workflows.
Get started by creating a new project ("File" -> "New project" -> "New Directory" -> "Quarto Website"), give it a name, and select "Open in new session" -> "Create Project" (@fig-quartoone).
::: {#fig-quartowebsiteftw layout-nrow="2" layout-valign="bottom"}
{#fig-quartoone}
{#fig-quartotwo}
{#fig-quartothree}
{#fig-quartofour}
Using Quarto to make a website
:::
The default basic website can be produced with "Build" -> "Render Website" (@fig-quartotwo). By default it may show in the "Viewer" pane, but can also be shown in a New Window, by . 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 (@fig-quartothree).
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 (@fig-quartofour). Another aspect that we can change in "_quarto.yml" is the theme. The default is "cosmo", but there are many other options specified [here](https://quarto.org/docs/output-formats/html-themes.html).
After the details are personalized and we are not unhappy with the website it can be pushed to GitHub and then hosted with GitHub Pages. To take advantage of that we need to first do two things. Firstly, we should slightly modify "_quarto.yml" to specify that we should build to a "docs" folder rather than "_site" (@fig-quartofour).
```{r}
#| eval: false
#| echo: true
project:
type: website
output-dir: docs
```
The other aspect to know is that when we use this service, 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:
```{r}
#| eval: false
#| echo: true
file.create(".nojekyll")
```
Then, assuming GitHub was set-up in @sec-reproducible-workflows, we can use `usethis` 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.
```{r}
#| eval: false
#| echo: true
use_git()
use_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, and finally "docs". After a few minutes to run through various checks, GitHub will let you know the address that you can share to visit your site.
To update the site, work locally. First pull, to ensure that any changes that GitHub made are present locally, then edit the site, re-render it and push it to GitHub in the usual manner. After the checks are completed the live website will update.
<!-- ### Distill -->
<!-- We will now use `distill` [@citedistill] to build additional infrastructure around our `postcards` site, following @hillpostcards. 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 @fig-distillone. -->
<!-- {#fig-distillone width=60% fig-align="center"} -->
<!-- At this point we can click "Build Website" in the Build tab, and we should see the default website (@fig-distilltwo). -->
<!-- {#fig-distilltwo width=90% fig-align="center"} -->
<!-- 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: -->
<!-- ```{r} -->
<!-- #| eval: false -->
<!-- #| echo: true -->
<!-- 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 @fig-distillthree it was added at line 15, and then we can rebuild. -->
<!-- {#fig-distillthree width=90% fig-align="center"} -->
<!-- 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" (@fig-distillfour). After this is done then we can rebuild the website, and the "software" page will have been added. -->
<!-- {#fig-distillfour width=90% fig-align="center"} -->
<!-- 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 @hillpostcards is a good starting point, in addition to the `distill` [homepage](https://rstudio.github.io/distill/). -->
<!-- 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. -->
<!-- ### Blogdown -->
<!-- Using `blogdown` [@citeblogdown] 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`. @citealisonhillblogdown and @blogdownbook 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" (@fig-blogdownone). -->
<!-- {#fig-blogdownone width=60% fig-align="center"} -->
<!-- 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 (@fig-blogdowntwo). -->
<!-- {#fig-blogdowntwo width=90% fig-align="center"} -->
<!-- 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](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. -->
<!-- One nice option is [Apéro](https://hugo-apero-docs.netlify.app). 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" (@fig-blogdownthree). -->
<!-- {#fig-blogdownthree width=60% fig-align="center"} -->
<!-- The result is the default Apéro website to which we could add our own details (@fig-apero-ex). -->
<!-- {#fig-apero-ex width=90% fig-align="center"} -->
## Client-side interactivity
Once we have a hosted website, one nice thing is that we can use it to "ship" some "light" interactivity. We will discuss more onerous approaches, such as a `shiny` app later, but these require a different skill set to share and deploy. Here we introduce a client-side solution, `crosstalk` and `plotly`, which will provide some interactivity, such as a tooltip, with little additional overhead.
## 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, we should 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, @mcquire2019one 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" [@washingtonpostmaps].
### Leaflet
We can use `leaflet` [@ChengKarambelkarXie2017] to make interactive maps. The essentials are similar to `ggmap` [@KahleWickham2013], but there are many additional aspects beyond that. We can redo the US military deployments map from @sec-static-communication that used `troopdata` [@troopdata]. 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 @sec-static-communication where we just picked a few particular countries. A great example of why this might be useful is provided by @theeconomistmaps 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 (@fig-canhasbase).
```{r}
#| fig-cap: "Interactive map of US bases"
#| label: fig-canhasbase
#| message: false
#| warning: false
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
addMarkers(
lng = bases$lon,
lat = bases$lat,
popup = bases$basename,
label = bases$countryname
)
```
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" [@fig-canhasbaseandmoney].
```{r}
#| fig-cap: "Interactive map of US bases with colored circules to indicate spend"
#| label: fig-canhasbaseandmoney
#| message: false
#| warning: false
build <-
get_builddata(startyear = 2008, endyear = 2019) |>
filter(!is.na(lon)) |>
mutate(
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
addCircleMarkers(
data = build,
lng = build$lon,
lat = build$lat,
color = pal(build$cost),
popup = paste(
"<b>Location:</b>",
as.character(build$location),
"<br>",
"<b>Amount:</b>",
as.character(build$spend_construction),
"<br>"
)
) |>
addLegend(
"bottomright",
pal = pal,
values = build$cost |> unique(),
title = "Type",
opacity = 1
)
```
### Mapdeck
`mapdeck` [@citemapdeck] 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](https://www.mapbox.com/). 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 @sec-gather-data) by running `edit_r_environ()`, which will open a text file, which is where we should add our Mapbox secret token.
```{r}
#| eval: false
MAPBOX_TOKEN <- "PUT_YOUR_MAPBOX_SECRET_HERE"
```
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 (@fig-canhasbaseandmoneymapdeck).
```{r}
#| fig-cap: "Interactive map of US bases using Mapdeck"
#| label: fig-canhasbaseandmoneymapdeck
#| message: false
#| warning: false
mapdeck(style = mapdeck_style("light")) |>
add_scatterplot(
data = build,
lat = "lat",
lon = "lon",
layer_id = "scatter_layer",
radius = 10,
radius_min_pixels = 5,
radius_max_pixels = 100,
tooltip = "location"
)
```
## Shiny
`shiny` [@citeshiny] 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 @theeconomistforecasts where they show how their forecasts of the 2022 French Presidential Election changed over time. We will return to `shiny` in @sec-its-just-a-linear-model.
We are going to make an interactive graph based on the "babynames" dataset from `babynames` [@citebabynames]. First, we will build a static version (@fig-babynames).
```{r}
#| fig-cap: "Popular baby names"
#| label: fig-babynames
#| message: false
#| warning: false
top_five_names_by_year <-
babynames |>
arrange(desc(n)) |>
slice_head(n = 5, by = c(year, sex))
top_five_names_by_year |>
ggplot(aes(x = n, fill = sex)) +
geom_histogram(position = "dodge") +
theme_minimal() +
scale_fill_brewer(palette = "Set1") +
labs(
x = "Babies with that name",
y = "Occurrences",
fill = "Sex"
)
```
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".
```{r}
#| eval: false
library(shiny)
# 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
sidebarLayout(
sidebarPanel(
sliderInput(
inputId = "number_of_bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30
)
),
# Show a plot of the generated distribution
mainPanel(plotOutput("distPlot"))
)
)
# 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") +
labs(
x = "Babies with that name",
y = "Occurrences",
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 @fig-shinyone.
{#fig-shinyone width=90% fig-align="center"}
## Exercises
### Scales {.unnumbered}
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.
### Questions {.unnumbered}
1. Based on @lovelace2019geocomputation, please explain in a paragraph or two, what is the difference between vector data and raster data in the context of geographic data?
2. Based on @wickham2021mastering, `shiny` uses:
a. Object-oriented programming
b. Functional programming
c. Reactive programming
3. In a paragraph or two, why is it important to have a website?
4. Which function should we use to stop GitHub itself from trying to build our site instead of just serving it (pick one)?
a. `file.create(".nojekyll")`
b. `file.remove(".nojekyll")`
c. `file.create(".jekyll")`
d. `file.remove(".jekyll")`
5. Which argument to `addMarkers()` is used to specify the behavior that occurs after a marker is clicked (pick one)?
a. `layerId`
b. `icon`
c. `popup`
d. `label`
### Tutorial {.unnumbered}
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 using the free tier of shinyapps.io.
Then, based on the themes brought up in @americaslavery, discuss your work in at least two pages. The expectation is that, similar to @kieranskitchen, you use your work as a foundation to build on and discuss what it means to use data about such a horror.
Use the starter folder, and submit a PDF created using the Quarto doc provided there. Ensure that your essay contains links to both your app and the GitHub repo that contains all code and data. As well as extensive citations to relevant literature that you reflected on.