Skip to content

Commit 96c0403

Browse files
kaijagahmlgibson7
andauthored
Programming with ggplot2 (#59)
* re-do the first few slides * update programming w ggplot2 slides * final edits * Add new line at the end of index.rmd * add {wesanderson} to dependencies * comment out `ggplot_global$theme_all_null` --------- Co-authored-by: Lydia Gibson <[email protected]>
1 parent 20286d3 commit 96c0403

File tree

3 files changed

+179
-84
lines changed

3 files changed

+179
-84
lines changed

18-Programming-with-ggplot2.Rmd

Lines changed: 176 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -14,59 +14,109 @@
1414
library(tidyverse)
1515
```
1616

17+
## Why program with {ggplot2}? {-}
1718

18-
**What are the components of a plot?**
19+
To reduce duplicated code, build up repeated components
1920

20-
- data.frame
21-
- aes()
22-
- Scales
23-
- Coords systems
24-
- Theme components
21+
Can also generalize code to allow for flexibility
2522

26-
## Programming single and multiple components
27-
28-
In ggplot2 it is possible to build up plot components easily. This is a good practice to reduce duplicated code.
29-
30-
Generalising code allows you with more flexibility when making customised plots.
31-
32-
### Components
23+
### Plot components are objects! {-}
3324

3425
One example of a component of a plot is this one below:
3526
```{r}
3627
bestfit <- geom_smooth(
3728
method = "lm",
3829
se = FALSE,
3930
colour = alpha("steelblue", 0.5),
40-
size = 2)
31+
linewidth = 2)
32+
class(bestfit)
4133
```
4234

43-
This single component can be placed inside the syntax of the grammar of graphics and used as a plot layer.
35+
## Adding the object we created to a plot {-}
36+
37+
Place component in grammar of graphics syntax to use as a plot layer
38+
4439
```{r}
4540
ggplot(mpg, aes(cty, hwy)) +
4641
geom_point() +
4742
bestfit
4843
```
4944

50-
Another way is to bulid a layer passing through build a function:
45+
## Creating a function {-}
46+
47+
Another way is to build a layer via a function:
5148
```{r}
5249
geom_lm <- function(formula = y ~ x, colour = alpha("steelblue", 0.5),
53-
size = 2, ...) {
50+
linewidth = 2, ...) {
5451
geom_smooth(formula = formula, se = FALSE, method = "lm", colour = colour,
55-
size = size, ...)
52+
linewidth = linewidth, ...)
5653
}
5754
```
5855

59-
And the apply the function layer to the plot
56+
Use the layer in the plot:
57+
```{r}
58+
ggplot(mpg, aes(displ, 1 / hwy)) +
59+
geom_point() +
60+
geom_lm(y ~ poly(x, 2), linewidth = 1, colour = "red")
61+
```
62+
63+
## `...` gives functions flexibility {-}
64+
65+
The `...` parameter lets a function accept additional arbitrary arguments
66+
67+
e.g. `na.rm` (doesn't make a difference in this case, but the function accepts it!)
68+
6069
```{r}
6170
ggplot(mpg, aes(displ, 1 / hwy)) +
6271
geom_point() +
63-
geom_lm(y ~ poly(x, 2), size = 1, colour = "red")
72+
geom_lm(y ~ poly(x, 2), linewidth = 1, colour = "red", na.rm = T)
6473
```
6574

66-
The book points out attention to the "open" parameter **...**.
67-
A suggestion is to use it inside the function instead of in the function parameters definition.
75+
## Exercises {-}
76+
77+
1. Create an object that represents a pink histogram with 100 bins.
78+
```{r}
79+
pinkhist <- geom_histogram(fill = "pink", bins = 100)
80+
ggplot(diamonds, aes(x = price)) +
81+
pinkhist +
82+
labs(y = "Frequency",
83+
x = "Price")
84+
```
85+
2. Create an object that represents a fill scale with the Blues ColorBrewer palette.
86+
```{r}
87+
blues_fill_scale <- scale_fill_brewer(palette = "Blues")
88+
ggplot(data = diamonds, aes(x = cut, y = price, fill = cut))+
89+
geom_boxplot()+
90+
theme_minimal()+
91+
blues_fill_scale
92+
```
93+
94+
3. Read the source code for theme_grey(). What are its arguments? How does it work?
95+
```{r}
96+
theme_grey
97+
# It creates a theme object called t
98+
# uses %+replace% to replace the existing theme with t
99+
100+
# ggplot_global$theme_all_null %+replace% t
101+
# ggplot_global$theme_all_null doesn't exist globally, so must refer to the current plot that you're adding theme_grey to.
102+
```
103+
104+
4. Create scale_colour_wesanderson(). It should have a parameter to pick the palette from the wesanderson package, and create either a continuous or discrete scale.
105+
```{r}
106+
library(wesanderson)
107+
scale_colour_wesanderson <- function(palette, type = "discrete", ...){
108+
scale_color_manual(values = wes_palette(name = palette, type = type, ...), ...)
109+
}
110+
ggplot(diamonds, aes(x = carat, y = price, color = cut))+
111+
geom_point()+
112+
scale_colour_wesanderson(palette = "Cavalcanti1")+
113+
theme_minimal()
114+
```
115+
116+
## A ggplot object is a list!
117+
118+
And therefore, we can add more than one component as a list.
68119

69-
Instead of only one component, we can build a plot made of more components.
70120
```{r}
71121
geom_mean <- function() {
72122
list(
@@ -76,17 +126,70 @@ geom_mean <- function() {
76126
}
77127
```
78128

79-
Whit this result:
80129
```{r message=FALSE, warning=FALSE, paged.print=FALSE}
81130
ggplot(mpg, aes(class, cty)) + geom_mean()
82131
```
83132

84133

85-
## Use components, annotation, and additional arguments in a plot
134+
## Components of a plot {-}
86135

87-
We have just seen some examples on how to make new components, what if we want to know more about existing components?
136+
- data.frame
137+
- aes()
138+
- Scales
139+
- Coords systems
140+
- Theme components
141+
142+
## We can add any of these to a plot and override existing {-}
143+
144+
For datasets, use `%+%`
145+
146+
```{r}
147+
dataset1 <- data.frame(id = rep(letters[1:3], each = 100),
148+
Value = c(rnorm(100, mean = 1),
149+
rnorm(100, mean = 2),
150+
rnorm(100, mean = 3)))
151+
152+
dataset2 <- data.frame(id = rep(letters[1:3], each = 100),
153+
Value = c(rpois(100, lambda = 1),
154+
rpois(100, lambda = 2),
155+
rpois(100, lambda = 3)))
156+
p1 <- ggplot(dataset1, aes(x = Value, col = id))+
157+
geom_density()+
158+
theme_minimal()
159+
p1
160+
161+
p2 <- p1 %+% dataset2
162+
p2
163+
```
164+
165+
## What if the dataset doesn't have the same variables? {-}
166+
167+
```{r error = T}
168+
dataset3 <- data.frame(id = rep(letters[1:3], each = 100),
169+
test = c(rpois(100, lambda = 4),
170+
rpois(100, lambda = 5),
171+
rpois(100, lambda = 6)))
88172
89-
As an example the `borders()` option function, provided by {ggplot2} to create a layer of map borders.
173+
# Try to add a new dataset, but it doesn't work because the code for p1 is expecting a "Value" column and that column doesn't exist in dataset3.
174+
p1 %+%
175+
dataset3
176+
```
177+
178+
Why doesn't this work?
179+
180+
```{r}
181+
# Let's override the y aesthetic...
182+
new_aes <- aes(y = test)
183+
184+
p3 <- p1 +
185+
new_aes %+%
186+
dataset3 #
187+
p3
188+
```
189+
190+
## Annotations {-}
191+
192+
Make sure to set `inherit.aes = FALSE` and `show.legend = FALSE`
90193

91194
> "A quick and dirty way to get map data (from the maps package) on to your plot."
92195
@@ -109,12 +212,14 @@ capitals <- subset(us.cities, capital == 2)
109212
110213
ggplot(capitals, aes(long, lat)) +
111214
borders("world", xlim = c(-130, -60), ylim = c(20, 50)) +
112-
geom_point(aes(size = pop)) +
215+
geom_point(aes(linewidth = pop)) +
113216
scale_size_area() +
114217
coord_quickmap()
115218
```
116219

117-
We can even add addtional arguments, such as those ones to modify and add things:
220+
## Additional arguments {-}
221+
222+
"If you want to pass additional arguments to the components in your function, ... is no good: there’s no way to direct different arguments to different components. Instead, you’ll need to think about how you want your function to work, balancing the benefits of having one function that does it all vs. the cost of having a complex function that’s harder to understand."
118223

119224
modifyList()
120225
do.call()
@@ -147,75 +252,64 @@ ggplot(mpg, aes(class, cty)) +
147252
)
148253
```
149254

150-
## Functional programming
151-
152-
An example is to make a geom. For this we can have a look at the **"Corporate Reputation"** data from #TidyTuesday 2022 week22.
153-
255+
## Making the complete plot--very limited flexibility {-}
154256
```{r}
155-
poll <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2022/2022-05-31/poll.csv')
156-
reputation <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2022/2022-05-31/reputation.csv')
157-
158-
159-
rep2<-reputation%>%
160-
group_by(company,industry)%>%
161-
summarize(score,rank)%>%
162-
ungroup()%>%
163-
mutate(year=2022)
164-
165-
166-
full <- poll%>%
167-
filter(!is.na(year))%>%
168-
full_join(rep2,by=c("2022_rank"="rank","2022_rq"="score","company","industry","year")) %>%
169-
count(year,company,industry,"rank"=`2022_rank`,"score"=`2022_rq`,sort=T) %>%
170-
arrange(-year)
257+
piechart <- function(data, mapping) {
258+
ggplot(data, mapping) +
259+
geom_bar(width = 1) +
260+
coord_polar(theta = "y") +
261+
xlab(NULL) +
262+
ylab(NULL)
263+
}
264+
piechart(mpg, aes(factor(1), fill = class))
265+
```
171266

172-
##################
267+
## What if we want to pass in different variables? {-}
173268

174-
# mapping = aes(x = fct_reorder(x,-y), y = y, fill = y, color = y, label = y)
269+
- Instead of writing out the entire `aes()`, the user can just pass in the variable names
270+
- But there's a catch!
175271

176-
rank_plot <- function(data,mapping) {
177-
data %>%
178-
ggplot(mapping)+ # aes(x=fct_reorder(x,-y),y=y)
179-
geom_col(width =0.3, # aes(fill=rank)
180-
show.legend = F)+
181-
geom_text(hjust=0,fontface="bold", # aes(label=rank,color=rank),
182-
show.legend = F)+
183-
scale_y_discrete(expand = c(0, 0, .5, 0))+
184-
coord_flip()+
185-
ggthemes::scale_fill_continuous_tableau(palette = "Green-Gold")+
186-
ggthemes::scale_color_continuous_tableau(palette = "Green-Gold")+
187-
labs(title="",
188-
x="",y="")+
189-
theme(axis.text.x = element_blank(),
190-
axis.text.y = element_text(face="bold"),
191-
axis.ticks.x = element_blank(),
192-
axis.ticks.y = element_line(size=2),
193-
panel.grid.major.x = element_blank(),
194-
panel.grid.minor.x = element_blank(),
195-
panel.grid.major.y = element_line(size=2),
196-
plot.background = element_rect(color="grey95",fill="grey95"),
197-
panel.background = element_rect(color="grey92",fill="grey92"))
272+
This doesn't work:
273+
```{r}
274+
my_function <- function(x_var) {
275+
aes(x = x_var)
198276
}
277+
my_function(abc)
278+
#> Aesthetic mapping:
279+
#> * `x` -> `x_var`
280+
```
199281

200-
df<-full%>%
201-
filter(year==2017,
202-
industry=="Retail")
282+
We can "embrace" the argument to tell ggplot2 to "look inside" the argument and use its value, not its expression
283+
```{r}
284+
my_function <- function(x_var) {
285+
aes(x = {{x_var}})
286+
}
287+
my_function(abc)
288+
#> Aesthetic mapping:
289+
#> * `x` -> `abc`
290+
```
203291

204-
rank_plot(data = df,
205-
mapping = aes(x=fct_reorder(company,-rank),y=rank,
206-
fill = rank, color = rank, label = rank))
292+
New version of the piechart function:
293+
```{r}
294+
piechart <- function(data, var) {
295+
ggplot(data, aes(factor(1), fill = {{ var }})) +
296+
geom_bar(width = 1) +
297+
coord_polar(theta = "y") +
298+
xlab(NULL) +
299+
ylab(NULL)
300+
}
301+
mpg |> piechart(class)
207302
```
208303

209-
## References
304+
305+
## References {-}
210306

211307
- [extending ggplot2](https://ggplot2.tidyverse.org/articles/extending-ggplot2.html)
212308
- [functions](https://adv-r.hadley.nz/functions.html)
213309
- [expressions](http://adv-r.had.co.nz/Expressions.html)
214310
- [functional programming](http://adv-r.had.co.nz/Functional-programming.html)
215311
- [advanced R - functionals](https://adv-r.hadley.nz/fp.html)
216312

217-
218-
219313
---
220314

221315
## Meeting Videos

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ Imports:
4343
SpatialEpi,
4444
tidyverse,
4545
tidygraph,
46-
png
46+
png,
47+
wesanderson
4748
Remotes:
4849
hadley/emo,
4950
drsimonj/ourworldindata,

index.Rmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,4 @@ to
112112
- Students who study with LOs in mind ***retain more.***
113113
- **Tips:**
114114
- "After today's session, you will be able to..."
115-
- *Very* roughly **1 per section.**
115+
- *Very* roughly **1 per section.**

0 commit comments

Comments
 (0)