-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchapter6.Rmd
797 lines (583 loc) · 26.6 KB
/
chapter6.Rmd
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
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
---
title: 'Chapter 6: Data visualisation with R'
description:
'This chapter will give you an introduction to the R graphics system and teach you how to get started with using the ggplot2 package for drawing all kind of plots.'
prev: /chapter5
next: /chapter7
type: chapter
id: 6
output:
teachr::teachr_chapter:
# html_document:
# self_contained: false
#md_document
---
```{r setup, include = FALSE}
library(teachr)
knitr::opts_chunk$set(fig.path = "ch6/",
fig.retina = 2,
fig.width = 6,
fig.height = 4,
fig.align = "center",
cache = FALSE,
cache.path = "cache/",
message = FALSE,
warning = FALSE)
#error = TRUE)
filter <- dplyr::filter
read_lines <- function(x) {
if(file.exists(x)) {
readLines(x)
} else {
""
}
}
```
<exercise id="1" title="R graphics" type="slides">
`r slides("chapter6_01_rgraphics")`
</exercise>
<exercise id="2" title="Test your knowledge of R graphics">
Which of the following is a contributed R package?
```{r, echo = FALSE, results = "asis"}
cat(mc_opts("ggplot2" = "That's correct! ggplot2 was developed by Hadley Wickham as part of his PhD.",
"grid" = "No, this is a core package so it's already installed.",
"graphics" = "No, this a core package and loads automatically when you launch R.",
"grDevices" = "No, this a core package and loads automatically when you launch R.",
correct = 1))
```
Which R package actually renders the graphics in R?
```{r, echo = FALSE, results = "asis"}
cat(mc_opts("ggplot2" = "No, that's incorrect.",
"grid" = "No, that's incorrect.",
"graphics" = "No, that's incorrect.",
"grDevices" = "Yes, that's right!",
correct = 4))
```
Remember that there are two primary graphic models in R: the base and grid graphics. Which one is ggplot2 using?
```{r, echo = FALSE, results = "asis"}
cat(mc_opts("base" = "No, that's incorrect.",
"grid" = "Yes that's right! Well done!",
correct = 2))
```
</exercise>
<exercise id="3" title="Getting started with ggplot2" type="slides">
`r slides("chapter6_02_ggplot2intro")`
</exercise>
<exercise id="4" title="Plotting two or more variables with ggplot2" type="slides">
`r slides("chapter6_03_ggplot2next")`
</exercise>
<exercise id="5" title="Make basic plots with ggplot2">
For the following questions we are going to use `BudgetFood` data from the `Ecdat` package which contains the budget share of food for Spanish households. You can load the dataset and see the structure of the data below.
```{r, message = FALSE, warning = FALSE}
library(Ecdat)
str(BudgetFood)
```
The meaning of the variables are described below:
* `wfood`: percentage of total expenditure which the household has spent on food
* `totexp`: total expenditure of the household
* `age`: age of reference person in the household
* `size`: size of the household
* `town`: size of the town where the household is placed categorized into 5 groups: 1 for small towns, 5 for big ones
* `sex`: sex of reference person (man,woman)
Try to recreate the scatter plot below. Is there anything unusual that you notice about the plot?
```{r plot-06-05A, code = read_lines("../exercises/solution_06_05A.R"), echo = FALSE}
```
```{teachr 06_05A, outdir = "../exercises"}
library(ggplot2)
data(BudgetFood, package = "Ecdat")
ggplot(data = {<BudgetFood>},
mapping = aes(x = {<size>},
y = {<totexp>})) +
geom_{<point>}()
---
Hint: The scatter plots are created using `geom_point`.
???
plot <- last_plot()
plot_has_point <- any(vapply(plot$layers, function(x) inherits(x$geom, "GeomPoint"), logical(1L)))
expect_true(
plot_has_point, info = "Your plot is missing the appropriate geom for a scatter plot."
)
plot_mapping <- aes(x = size, y = totexp)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x and/or y axis are incorrect."
)
```
You may have noticed that there is _overplotting_ in the previous plot for the bottom left region. Let's try to create a **hex plot** like below this time.
```{r plot-06-05B, code = read_lines("../exercises/solution_06_05B.R"), echo = FALSE}
```
```{teachr 06_05B, outdir = "../exercises"}
ggplot(data = {<BudgetFood>},
mapping = aes(x = {<size>},
y = {<totexp>})) +
geom_{<hex>}()
---
Hint: The hex plots are created using `geom_hex`.
???
plot <- last_plot()
plot_has_hex <- any(vapply(plot$layers, function(x) inherits(x$geom, "GeomHex"), logical(1L)))
expect_true(
plot_has_hex, info = "Your plot is missing the appropriate geom for a hex plot."
)
plot_mapping <- aes(x = size, y = totexp)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x and/or y axis are incorrect."
)
```
This time let's have a look at some other variables in the `BudgetFood` data. Let's check the distribution of the age by sex using **boxplot** like below.
```{r plot-06-05C, code = read_lines("../exercises/solution_06_05C.R"), echo = FALSE}
```
```{teachr 06_05C, outdir = "../exercises"}
ggplot(data = {<BudgetFood>},
mapping = aes(x = {<sex>},
y = {<age>})) +
geom_{<boxplot>}()
---
Hint: The five number summary is often graphically depicted by a boxplot.
???
plot <- last_plot()
plot_has_boxplot <- any(vapply(plot$layers, function(x) inherits(x$geom, "GeomBoxplot"), logical(1L)))
expect_true(
plot_has_boxplot, info = "Your plot is missing the appropriate geom for a boxplot."
)
plot_mapping <- aes(x = sex, y = age)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x and/or y axis are incorrect."
)
```
Next study the distribution of the total expenditure of the household by size of the town using a **violin plot** like below.
```{r plot-06-05D, code = read_lines("../exercises/solution_06_05D.R"), echo = FALSE}
```
```{teachr 06_05D, outdir = "../exercises"}
ggplot(data = {<BudgetFood>},
mapping = aes(x = {<factor(town)>},
y = {<totexp>})) +
geom_{<violin>}()
---
Hint: what do you notice about the x-axis scale? Do you perhaps need to convert `town`?
???
plot <- last_plot()
plot_has_violin <- any(vapply(plot$layers, function(x) inherits(x$geom, "GeomViolin"), logical(1L)))
expect_true(
plot_has_violin, info = "Your plot is missing the appropriate geom for a violin plot."
)
plot_mapping <- aes(x = factor(town), y = totexp)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x and/or y axis are incorrect."
)
```
Let's have a look at the distribution of the percentage of total expenditure which the household has spent on food (`wfood`). We'll adjust the bin width of the **histogram** to 0.001. Do you notice the peak at 0?
```{r plot-06-05E, code = read_lines("../exercises/solution_06_05E.R"), echo = FALSE}
```
```{teachr 06_05E, outdir = "../exercises"}
ggplot(data = {<BudgetFood>},
mapping = aes(x = {<wfood>})) +
geom_{<histogram>}(binwidth = 0.001)
---
Hint: this plot is called a histogram.
???
plot <- last_plot()
plot_has_hist <- any(vapply(plot$layers, function(x) inherits(x$geom, "GeomBar"), logical(1L)))
expect_true(
plot_has_hist, info = "Your plot is missing the appropriate geom for a scatter plot."
)
plot_mapping <- aes(x = wfood)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x axis are incorrect."
)
```
Finally, let's also draw a density plot but display the y-axis as counts instead of density.
```{r plot-06-05F, code = read_lines("../exercises/solution_06_05F.R"), echo = FALSE}
```
```{teachr 06_05F, outdir = "../exercises"}
ggplot(data = {<BudgetFood>},
mapping = aes(x = {<wfood>})) +
geom_density(aes(y = {<after_stat(count)>}))
---
Hint: this is a density plot but the y-axis is showing counts. What did `after_stat` function do?
???
plot <- last_plot()
plot_has_density <- vapply(plot$layers, function(x) inherits(x$geom, "GeomDensity"), logical(1L))
expect_true(
any(plot_has_density), info = "Your plot is missing the appropriate geom for a density plot."
)
plot_mapping <- aes(x = wfood)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x axis is incorrect."
)
density_mapping <- plot$layers[[which(plot_has_density)[1]]]$mapping
geom_mapping <- aes(y = after_stat(count))
expect_equal(
density_mapping, geom_mapping, info = "The variable on your y axis is incorrect. Have you tried using the after_stat() function to show the computed count variable?"
)
```
</exercise>
<exercise id="6" title="Multiple layers and attributes in ggplot2" type="slides">
`r slides("chapter6_04_ggplot2layers")`
</exercise>
<exercise id="7" title="Practice creating multiple layers">
We are again going to use the `BudgetFood` data from the `Ecdat` package to make the plots.
The plot below shows the histogram with the density plot overlaid on top of it. Try to recreate this figure.
```{r plot-06-07A, code = read_lines("../exercises/solution_06_07A.R"), echo = FALSE}
```
```{teachr 06_07A, outdir = "../exercises"}
ggplot(data = {<BudgetFood>},
mapping = aes(x = {<totexp>})) +
geom_{<histogram>}(aes(y = after_stat(density))) +
geom_{<density>}(colour = "red")
---
Hint: this is a density plot but the y-axis is showing counts. What did `after_stat` function do?
???
plot <- last_plot()
plot_has_density <- vapply(plot$layers, function(x) inherits(x$geom, "GeomDensity"), logical(1L))
expect_true(
any(plot_has_density), info = "Your plot is missing the appropriate geom for a density plot."
)
plot_has_hist <- vapply(plot$layers, function(x) inherits(x$geom, "GeomBar"), logical(1L))
expect_true(
any(plot_has_hist), info = "Your plot is missing the appropriate geom for a histogram plot."
)
plot_mapping <- aes(x = totexp)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x axis is incorrect."
)
hist_mapping <- plot$layers[[which(plot_has_hist)[1]]]$mapping
geom_mapping <- aes(y = after_stat(density))
expect_equal(
hist_mapping, geom_mapping, info = "The variable on your y axis is incorrect. Have you tried using the after_stat() function to show the computed density variable for the histogram?"
)
density_aes <- plot$layers[[which(plot_has_density)[[1]]]]$aes_params
density_colour <- rlang::`%||%`(density_aes$color, density_aes$colour)
expect_equal(
density_colour, "red", info = "The colour of the density line geometry is not red."
)
```
In the next target plot, we are going to look at the distribution of the `age` by `sex`. There are not that many observations where sex information is missing so let's focus on `sex` levels for "man" and "woman".
```{r plot-06-7B, code = read_lines("../exercises/solution_06_07B.R"), echo = FALSE}
```
```{teachr 06_07B, outdir = "../exercises"}
library(tidyverse)
BudgetFood %>%
{<filter>}({<!is.na(sex)>}) %>%
ggplot(
mapping = aes(x = {<sex>}, y = {<age>})
) +
geom_{<violin>}({<aes(fill = sex)>}) +
geom_{<boxplot>}({<width>} = 0.1)
---
Hint: Use the `width` argument to change the width of the boxplot.
???
plot <- last_plot()
solution_data <- dplyr::filter(BudgetFood, !is.na(sex))
expect_equal(plot$data, solution_data, info = "The data has not been correctly filtered to look at only data where `sex` is 'man' or 'woman'.")
plot_has_violin <- vapply(plot$layers, function(x) inherits(x$geom, "GeomViolin"), logical(1L))
expect_true(
any(plot_has_violin), info = "Your plot is missing the appropriate geom for a violin plot."
)
plot_has_boxplot <- vapply(plot$layers, function(x) inherits(x$geom, "GeomBoxplot"), logical(1L))
expect_true(
any(plot_has_boxplot), info = "Your plot is missing the appropriate geom for a boxplot."
)
plot_mapping <- aes(x = sex, y = age)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x and/or y axis is incorrect."
)
violin_mapping <- plot$layers[[which(plot_has_violin)[1]]]$mapping
geom_mapping <- aes(fill = sex)
expect_equal(
violin_mapping, geom_mapping, info = "The variable used to fill the violins is incorrect."
)
boxplot_width <- plot$layers[[which(plot_has_boxplot)[[1]]]]$geom_params$width
expect_equal(
boxplot_width, 0.1, info = "The boxplot width has not been correctly specified."
)
```
In the next target plot, we want to draw a scatter plot between the size of the household and the total expenditure of the household. Then we want to overlay this with a loess curve in red colour. You may not have seen how to fit a curve on `ggplot` yet so check out the hint if you don't know.
```{r plot-06-07C, code = read_lines("../exercises/solution_06_07C.R"), echo = FALSE}
```
```{teachr 06_07C, outdir = "../exercises"}
BudgetFood %>%
filter({<size < 30>}) %>%
ggplot(
mapping = aes(x = {<size>}, y = {<totexp>})
) +
geom_{<point>}() +
geom_{<smooth>}(colour = "red",
method = loess,
formula = y ~ x)
---
Hint: `geom_smooth` can draw curves from a fitted model.
???
plot <- last_plot()
solution_data <- dplyr::filter(BudgetFood, size < 30)
expect_equal(plot$data, solution_data, info = "The data has not been correctly filtered to look at only data size is less than 30.")
plot_has_point <- vapply(plot$layers, function(x) inherits(x$geom, "GeomPoint"), logical(1L))
expect_true(
any(plot_has_point), info = "Your plot is missing the appropriate geom for a scatter plot."
)
plot_has_smooth <- vapply(plot$layers, function(x) inherits(x$geom, "GeomSmooth"), logical(1L))
expect_true(
any(plot_has_smooth), info = "Your plot is missing the appropriate geom for a smooth fitted model through the data."
)
plot_mapping <- aes(x = size, y = totexp)
expect_equal(
plot$mapping, plot_mapping, info = "The variables on your x and/or y axis is incorrect."
)
smooth_aes <- plot$layers[[which(plot_has_smooth)[[1]]]]$aes_params
smooth_colour <- rlang::`%||%`(smooth_aes$color, smooth_aes$colour)
expect_equal(
smooth_colour, "red", info = "The colour of the smooth line geometry is not red."
)
```
In the next plot, try drawing a **barplot** by the different sexes with the total count written on top of the bar.
```{r plot-06-07D, code = read_lines("../exercises/solution_06_07D.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_07D, outdir = "../exercises"}
BudgetFood %>%
filter({<!is.na(sex)>}) %>%
ggplot(mapping = aes(x = {<sex>})) +
geom_{<bar>}() +
geom_{<text>}(
aes(label = {<after_stat(count)>}),
vjust = -0.3,
stat = {<"count">}
)
---
Hint: change the stat of one of the geometry used to write the count to compute the total count to be used on the y axis.
???
plot <- last_plot()
solution_data <- dplyr::filter(BudgetFood, !is.na(sex))
expect_equal(plot$data[colnames(solution_data)], solution_data, info = "The data has not been correctly filtered to look at only data where `sex` is 'man' or 'woman'.")
plot_has_bar <- vapply(plot$layers, function(x) inherits(x$geom, "GeomBar"), logical(1L))
expect_true(
any(plot_has_bar), info = "Your plot is missing the appropriate geom for a bar plot."
)
plot_has_text <- vapply(plot$layers, function(x) inherits(x$geom, "GeomText"), logical(1L))
expect_true(
any(plot_has_text), info = "Your plot is missing the appropriate geom for a text shown above the bars."
)
plot_mapping <- aes(x = sex)
expect_equal(
plot$mapping, plot_mapping, info = "The variable on your x axis is incorrect."
)
text_aes <- plot$layers[[which(plot_has_text)[[1]]]]$mapping
text_aes_solution <- aes(label = after_stat(count))
expect_equal(
text_aes, text_aes_solution, info = "The aesthetics for your text labels are incorrect. Hint: this can be computed with after_stat()."
)
has_text_stat <- inherits(plot$layers[[which(plot_has_text)[[1]]]]$stat, "StatCount")
expect_true(
has_text_stat, info = "Your text geometry is missng the stat used to compute the appropriate position on the y-axis."
)
```
The next one might be tricky. You want to draw a bar plot showing the average total expenditure of by sex and town but the top blue bars show the average for women, while the bottom red bars show the average for men.
```{r plot-06-07E, code = read_lines("../exercises/solution_06_07E.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_07E, outdir = "../exercises"}
library(tidyverse)
dat <- BudgetFood %>%
filter(!is.na(sex)) %>%
group_by(town, sex) %>%
summarise(totexp = mean(totexp))
{<ggplot()>} +
geom_{<col>}(data = filter(dat, sex=="woman"),
aes(x = {<factor(town)>},
y = {<totexp>},
{<fill = "woman">})) +
geom_{<col>}(data = subset(dat, sex=="man"),
aes(x = {<factor(town)>},
y = {<-totexp>},
{<fill = "man">}))
---
Hint: The legend shows the `fill` with a label "woman" and "man". In this case should `fill` be an attribute or aesthetic?
???
plot <- last_plot()
plot_has_cols <- vapply(plot$layers, function(x) inherits(x$geom, "GeomCol"), logical(1L))
expect_true(
all(plot_has_cols), info = "Your is using the incorrect geometry type."
)
col_aes <- plot$layers[[which(plot_has_cols)[[1]]]]$mapping
col_aes_solution <- aes(x = factor(town), y = totexp, fill = "woman")
expect_equal(
col_aes, col_aes_solution, info = "The aesthetics for your geometry plotting `sex==\"woman\"` is incorrect. Have you set the fill aethetic correctly?"
)
col_aes <- plot$layers[[which(plot_has_cols)[[2]]]]$mapping
col_aes_solution <- aes(x = factor(town), y = -totexp, fill = "man")
expect_equal(
col_aes, col_aes_solution, info = "The aesthetics for your geometry plotting `sex==\"man\"` is incorrect. Have you set the fill aethetic correctly?"
)
```
</exercise>
<exercise id="8" title="Scales and guides in ggplot2" type="slides">
`r slides("chapter6_05_ggplot2scales")`
</exercise>
<exercise id="9" title="Practice changing scales">
In the plot below, we show the age distribution by man and woman. Change the colour so the violin plot for the man coloured as "violet" and woman as "royalblue".
```{r plot-06-09A, code = read_lines("../exercises/solution_06_09A.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_09A, outdir = "../exercises"}
ggplot(data = subset(BudgetFood, !is.na(sex)),
mapping = aes(x = sex,
y = age)) +
geom_violin(aes(fill = sex)) +
{<scale_fill>}_manual(values = c("violet", "royalblue"))
---
Hint: Recall that scales are controlled by functions beginning with `scale_`. The second "word" in the scale function is the aesthetic.
???
plot <- last_plot()
plot_scale <- vapply(plot$scales$scales, function(x) x$aesthetics == "fill", logical(1L))
expect_true(plot_scale, info = "The scale function has been incorrectly specified.")
```
In the next plot, let's have a look at the distribution of the total household expenditure by sex using histograms. Since the total household expenditure skewed to the right, take a log with base 10 transformation for the scale and change the colours like the target plot below.
```{r plot-06-09B, code = read_lines("../exercises/solution_06_09B.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_09B, outdir = "../exercises"}
ggplot(data = subset(BudgetFood, !is.na(sex)),
mapping = aes(x = totexp,
fill = sex)) +
geom_histogram(bins = 40,
aes(colour = sex)) +
{<scale_x>}_log10() +
{<scale_colour>}_discrete() +
{<scale_fill>}_brewer(palette = 10)
---
Hint: Recall that scales are controlled by functions beginning with `scale_`. The second "word" in the scale function is the aesthetic.
???
plot <- last_plot()
log10_scale <- vapply(plot$scales$scales, function(x) "x" %in% x$aesthetics, logical(1L))
discrete_scale <- vapply(plot$scales$scales, function(x) any(c("color", "colour") %in% x$aesthetics), logical(1L))
brewer_scale <- vapply(plot$scales$scales, function(x) "fill" %in% x$aesthetics, logical(1L))
log10_answer <- which(log10_scale) == 1L
discrete_answer <- which(discrete_scale) == 2L
brewer_answer <- which(brewer_scale) == 3L
expect_true(log10_answer, info = "The answer for the *_log10() scale is incorrect.")
expect_true(discrete_answer, info = "The answer for the *_discrete() scale is incorrect.")
expect_true(brewer_answer, info = "The answer for the *_brewer() scale is incorrect.")
```
</exercise>
<exercise id="10" title="Multiple plots in one figure" type="slides">
`r slides("chapter6_06_ggplot2facet")`
</exercise>
<exercise id="11" title="Practice making multiple subplots">
In the following section, we won't give you much hints! Try to reach the target plots by seeing what's drawn in the target plot and complete the code needed to get to the target plot.
```{r plot-06-11A, code = read_lines("../exercises/solution_06_11A.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_11A, outdir = "../exercises"}
ggplot(BudgetFood, aes(x = {<age>})) +
geom_histogram(data = {<select(BudgetFood, -town)>},
fill = "grey", binwidth = 1,
aes(y = after_stat(density))) +
geom_histogram(aes(y = after_stat(density)),
binwidth = 1) +
geom_density(colour = "red") +
facet_{<wrap(~town)>}
---
Hint: what variable is the data facetted by? If you want to see the grey shadow of the overall distribution for each panel, remember that the variable needs to be removed from the layer data.
???
plot <- last_plot()
answer_mapping <- aes(x = age)
expect_equal(plot$mapping, answer_mapping, info = "The plot's mapping variables are incorrect.")
facet_type <- inherits(plot$facet, "FacetWrap")
expect_true(facet_type, info = "The facet type is incorrect.")
facet_vars <- identical(names(plot$facet$params$facets), "town")
expect_true(facet_type, info = "The variable facetting the plot is incorrect.")
```
```{r plot-06-11B, code = read_lines("../exercises/solution_06_11B.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_11B, outdir = "../exercises"}
ggplot(subset(BudgetFood, !is.na(sex)), aes(age)) +
geom_histogram(aes(y = {<after_stat(density)>})) +
geom_text(x = 35, y = 0.035,
data = function(.data) .data %>%
group_by(sex, town) %>%
count(),
aes(label = n)) +
facet_{<grid(sex ~ town)>}
---
Hint: A different style of facet is required to arrange the subplots in both x and y directions.
???
plot <- last_plot()
answer_mapping <- aes(x = age)
expect_equal(plot$mapping, answer_mapping, info = "The plot's mapping variables are incorrect.")
facet_type <- inherits(plot$facet, "FacetGrid")
expect_true(facet_type, info = "The facet type is incorrect.")
facet_rows <- identical(names(plot$facet$params$rows), "sex")
facet_cols <- identical(names(plot$facet$params$cols), "town")
expect_true(facet_rows, info = "The variable row facetting the plot is incorrect.")
expect_true(facet_cols, info = "The variable column facetting the plot is incorrect.")
plot_has_hist <- vapply(plot$layers, function(x) inherits(x$geom, "GeomBar"), logical(1L))
hist_aes <- plot$layers[[which(plot_has_hist)[[1]]]]$mapping
hist_aes_solution <- aes(y = after_stat(density))
expect_equal(
hist_aes, hist_aes_solution, info = "The aesthetics for your histogram are incorrect. Note that you'll need to use after_stat() to use the variables computed by the histogram stat."
)
```
```{r plot-06-11C, code = read_lines("../exercises/solution_06_11C.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_11C, outdir = "../exercises"}
library(tidyverse)
library({<patchwork>})
g1 <- ggplot(BudgetFood,
aes(factor(size), wfood, colour = sex)) +
geom_boxplot()
g2 <- ggplot(BudgetFood,
aes(factor(size), totexp, colour = sex)) +
geom_boxplot() +
scale_y_log10()
# combine the plot as one figure
{<g1 / g2>} + plot_layout(guides = "collect")
---
Hint: The patchwork package allows you to arbitrarily combine multiple separate plots.
???
expect_true(
"patchwork" %in% loadedNamespaces(),
info = "You haven't loaded a package which allows you to combine g1 and g2."
)
plot <- last_plot()
expect_true(inherits(plot, "patchwork"), info = "The plot outputted does not use the patchwork package to produce it.")
```
</exercise>
<exercise id="12" title="Customise the look with themes in ggplot2" type="slides">
`r slides("chapter6_07_ggplot2theme")`
</exercise>
<exercise id="13" title="Make pretty plots">
Well done getting to the last practice exercise!
The next plot you're going to draw is the plot below -- or make the plot as pretty as you can!
```{r plot-06-13A, code = read_lines("../exercises/solution_06_13A.R"), echo = FALSE, cache = FALSE}
```
```{teachr 06_13A, outdir = "../exercises"}
ggplot(BudgetFood, aes(x = age)) +
geom_histogram(aes(y = after_stat(density)),
binwidth = 1) +
geom_density(colour = "red") +
facet_wrap(~town, labeller = label_both) +
labs(x = "Age", y = "Density", title = "Age distribution by town size") +
theme(text = {<element_text>}(size = 14, family = "mono"),
plot.background = {<element_rect>}(fill = "grey80"),
{<strip.background>} = element_rect(fill = "black"),
{<strip.text>} = element_text(color = "white"),
panel.background = {<element_rect>}(fill = "white",
color = "black"),
panel.grid = element_blank())
---
Hint: Theme options for ggplot2 are customised in the theme() function. You specify how a particular target (say the text) is shown using the appropriate `element_*()` function.
???
plot <- last_plot()
theme_answer <- theme(text = element_text(size = 14, family = "mono"),
plot.background = element_rect(fill = "grey80"),
strip.background = element_rect(fill = "black"),
strip.text = element_text(color = "white"),
panel.background = element_rect(fill = "white",
color = "black"),
panel.grid = element_blank())
expect_equivalent(plot$theme, theme_answer, info = "The theme specified does not exactly match the plot shown above. Check that you are targeting the correct element for each customisation.")
```
</exercise>
<exercise id="14" title="Resources">
* [ggplot2: elegant graphics for data analysis](https://ggplot2-book.org/)
* [R Graphics Cookbook](https://r-graphics.org/)
* [R for data science slack community](https://rfordatascience.slack.com/join/shared_invite/zt-13ohm2as3-k3Vl31J54zTOjw1h3wpAuQ#/shared-invite/email) has a channel on `ggplot2`
* [Download](https://raw.githubusercontent.com/rstudio/cheatsheets/main/data-visualization.pdf) the `ggplot2` cheat sheet
* Ask or search questions at [StackOverflow](https://stackoverflow.com/questions/tagged/ggplot2) or [RStudio Community](https://community.rstudio.com/tag/ggplot2) with `ggplot2` tag.
* [The R Graph Gallery](https://www.r-graph-gallery.com/)
* [Fundamentals of Data Visualization](https://clauswilke.com/dataviz/) -- see code for this book [here](https://github.com/clauswilke/dataviz).
</exercise>