1414library(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
3425One example of a component of a plot is this one below:
3526``` {r}
3627bestfit <- 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}
4540ggplot(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}
5249geom_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}
6170ggplot(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}
71121geom_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}
81130ggplot(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
110213ggplot(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
0 commit comments