1
1
---
2
- title : " Animating Plots in R"
2
+ title : " So You're Thinking About Animating a Plot in R"
3
3
subtitle : " DC R 2019"
4
4
author : " Stephanie Kirmer <BR> [www.stephaniekirmer.com](http://www.stephaniekirmer.com) <BR> @[data_stephanie](http://www.twitter.com/data_stephanie)"
5
5
date : " November 8, 2019"
@@ -15,8 +15,6 @@ library(gganimate)
15
15
16
16
```
17
17
18
- # Agenda | <BR > Animation: When and Why? <BR > Introducing the Tools <BR > Building the Viz
19
-
20
18
# Follow Along! | https://github.com/skirmer/animating_dataviz
21
19
22
20
<div class =" notes " >
@@ -25,7 +23,7 @@ Introductions, get the about-me out of the way and give a quick overview
25
23
</div >
26
24
27
25
28
- ## So You're Thinking About Animating | What are some reasons to animate a plot?
26
+ ## Should you animate that plot?
29
27
30
28
### ** Bad Reasons**
31
29
@@ -43,8 +41,8 @@ Also: If you need to see all the data points at the same time, don't use animati
43
41
<div class =" notes " >
44
42
Balance between encouragement and caution
45
43
46
- Time does not necessarily need to be represented in actual temporality
47
- Talk about what Meaningful Data Dimensions means
44
+ Time does not necessarily need to be represented in actual temporality
45
+ Talk about what Meaningful Data Dimensions means
48
46
Talk about levels of dimension as factor
49
47
50
48
</div >
@@ -78,8 +76,8 @@ Thomas Lin Pedersen's example from https://gganimate.com - (@[thomasp85](https:/
78
76
</div >
79
77
80
78
<div class =" notes " >
81
- TLP is the creator of gganimate- encourage people to check his stuff out
82
- Discuss this specific plot- what can you learn from it and what is it not good for?
79
+ TLP is the creator of gganimate- encourage people to check his stuff out
80
+ Discuss this specific plot- what can you learn from it and what is it not good for?
83
81
84
82
- trends? y/n
85
83
- comparisons across continents? y/n
@@ -114,15 +112,16 @@ Discuss this specific plot- what can you learn from it and what is it not good f
114
112
</div >
115
113
116
114
<div class =" notes " >
117
- Show these examples in realtime - tell people to google for more to get ideas
115
+ Show these examples in realtime - tell people to google for more to get ideas
118
116
It can be hard to imagine your data in an animation, so looking at examples of how other people do it can be v helpful
119
117
</div >
120
118
121
- ## Think About the Design
119
+ ## Think About Design
120
+
121
+ - What information do you want the audience to take away?
122
+
123
+ - Movement and speed lead the viewer to interpretation of the data - this can be good or bad
122
124
123
- - What information do you want the audience to take away?
124
- - Movement leads the viewer to interpretation of the data - this can be good or bad
125
- - Speed creates meaning, be conscious of that
126
125
- Each static frame should be informative alone as well
127
126
128
127
(Be open to the idea that you might not need animation to be most effective)
@@ -172,7 +171,7 @@ To make the example here work, you need the first three for sure- some different
172
171
These are really concepts in the space of animation generally
173
172
Think about old timey cartooning, or flipbooks- one cel at a time, moving past you quick enough that it looks like movement
174
173
What we are doing here is not dissimilar.
175
- Frame: a measure of time. State: a property of your data.
174
+ Frame: a measure of time. State: a property of your data.
176
175
Option: look back at the examples from earlier and talk about what the states are?
177
176
</div >
178
177
@@ -234,14 +233,15 @@ knitr::kable(head(plotDT, 4))
234
233
Group by country, bar height is affected persons
235
234
236
235
``` {r}
237
- baseplot1 <- ggplot(plotDT,
238
- aes(X_date_year,
239
- group = X_country_origin,
240
- fill = as.factor(X_country_origin),
241
- color = as.factor(X_country_origin)))+
242
- theme_bw()+
243
- theme(legend.position = "bottom")+
244
- geom_bar(aes(y = X_affected), stat = "identity", position = "dodge")
236
+ baseplot1 <- ggplot(
237
+ plotDT,
238
+ aes(X_date_year,
239
+ group = X_country_origin,
240
+ fill = as.factor(X_country_origin),
241
+ color = as.factor(X_country_origin))) +
242
+ theme_bw() +
243
+ theme(legend.position = "bottom") +
244
+ geom_bar(aes(y = X_affected), stat = "identity", position = "dodge")
245
245
246
246
```
247
247
@@ -254,41 +254,74 @@ Ew. This is not effective.
254
254
baseplot1
255
255
```
256
256
257
+ ## Can Faceting Solve?
258
+
259
+ No.
260
+
261
+ ``` {r, echo=FALSE, fig.width = 10}
262
+ baseplot1+facet_grid(X_country_origin~.)
263
+ ```
264
+
265
+ ## Can Faceting Solve?
266
+
267
+ Nooooo.
268
+
269
+ ``` {r, echo=FALSE, fig.width = 10}
270
+ baseplot1+facet_wrap(X_country_origin~.)
271
+ ```
272
+
273
+
257
274
## What if we try to make a race plot instead?
258
275
259
276
![ Let's make this!] ( final_race_plot2.gif )
260
277
261
278
262
279
## Reformat the Plot
263
280
264
- Flip axis, change axes and margins, change grouping, etc.
281
+ From this...
282
+
283
+ ``` {r}
284
+ baseplot1 <- ggplot(plotDT,
285
+ aes(X_date_year,
286
+ group = X_country_origin,
287
+ fill = as.factor(X_country_origin),
288
+ color = as.factor(X_country_origin))) +
289
+ theme_bw() +
290
+ theme(legend.position = "bottom") +
291
+ geom_bar(aes(y = X_affected), stat = "identity", position = "dodge")
292
+
293
+ ```
294
+
295
+ ## Reformat the Plot
296
+
297
+ To this!
265
298
266
299
``` {r}
267
300
baseplot3 <- ggplot(plotDT,
268
301
### <b>
269
302
aes(x=rank,
303
+ ### </b>
270
304
group = X_country_origin,
271
305
fill = as.factor(X_country_origin),
272
306
color = as.factor(X_country_origin)))+
273
- ### </b>
274
- theme_bw()+
275
- ### <b>
276
- theme(legend.position = "none",
307
+ theme_bw()+
308
+ ### <b>
309
+ theme(legend.position = "none", # Give the plot enough space to have labels
277
310
axis.ticks.y = element_blank(),
278
311
axis.text.y = element_blank(),
279
312
axis.title.y = element_blank(),
280
313
plot.margin = margin(1,1,1,5, "cm"))+
281
- ### </b>
282
- geom_text(aes(y = 0, label = paste(X_country_origin, " ")), vjust = 0.2, hjust = 1) +
283
- coord_flip(clip = "off", expand = FALSE, ylim = c(0, 50000)) +
284
- ### <b>
285
- geom_bar(aes(y = X_affected), stat = "identity", position = "identity")+
286
- scale_y_continuous(labels = scales::comma) +
287
- scale_x_reverse()
288
- ### </b>
314
+ geom_text(aes(y = 0, label = paste(X_country_origin, " ")), vjust = 0.2, hjust = 1) +
315
+ coord_flip(clip = "off", expand = FALSE, ylim = c(0, 50000)) + # Flip the plot
316
+ ### </b>
317
+ geom_bar(aes(y = X_affected), stat = "identity", position = "identity")+
318
+ ### <b>
319
+ scale_y_continuous(labels = scales::comma) +
320
+ scale_x_reverse()
321
+ ### </b>
289
322
290
323
```
291
-
324
+ </ div >
292
325
293
326
## Render
294
327
@@ -297,33 +330,6 @@ Now we have the different "frames" all layered on top of each other.
297
330
baseplot3
298
331
```
299
332
300
- ## Decision Point: How to Proceed? | Before continuing - are we SURE animation is our best option?
301
-
302
- Revisit our goals:
303
-
304
- 1 . Where do most refugees come from?
305
- 2 . Over time, are the most common countries of origin about the same?
306
- 3 . Is the number of refugees coming from the most common countries of origin stable?
307
-
308
- Let's try static options one last time just to be sure.
309
-
310
- ## Faceting?
311
-
312
- ``` {r, echo = FALSE, fig.width = 10}
313
- baseplot3+facet_wrap(X_date_year~.)
314
- ```
315
-
316
- No.
317
-
318
-
319
- ## Faceting?
320
-
321
- ``` {r, echo = FALSE, fig.width = 10}
322
- baseplot3+facet_grid(X_date_year~.)
323
- ```
324
-
325
- Definitely not.
326
-
327
333
# Develop the Animation
328
334
329
335
## Basic Version
@@ -338,7 +344,7 @@ animp <- baseplot3 +
338
344
### </b>
339
345
```
340
346
341
- ## Basic Animation - Render
347
+ ## It's Alive!
342
348
343
349
<div class =" columns-2 " >
344
350
``` {r, fig.width = 8, fig.height=4, echo = FALSE, cache = TRUE}
@@ -371,15 +377,15 @@ animp <- baseplot3 +
371
377
372
378
```
373
379
374
- ## Dynamic Labels - Render
380
+ ## Dynamic Labels
375
381
376
382
``` {r, fig.width = 10, fig.height=6, echo = FALSE, cache = TRUE}
377
383
378
384
animate(animp, fps = 10, duration = 20)
379
385
380
386
```
381
387
382
- ## Transition Options: Exit/Enter
388
+ ## How Things Move
383
389
384
390
Solving Problem 3: how do we want the animation elements to move?
385
391
@@ -402,7 +408,7 @@ animp <- baseplot3 +
402
408
```
403
409
404
410
405
- ## Exit/Enter - Render
411
+ ## Exit/Enter
406
412
407
413
It's interesting, but probably not serving the project objectives
408
414
@@ -413,10 +419,13 @@ animate(animp, fps = 10, duration = 20)
413
419
```
414
420
415
421
416
- ## Transition Options: Easing
422
+ ## How More Things Move
423
+
424
+ Choose easing:
425
+
426
+ * movement between positions (moving on page, not exiting or entering)
427
+ * transition speed can change as it moves (functions may be cubic, quartic, etc)
417
428
418
- Choose easing: movement between positions (moving on page, not exiting or entering)
419
- Makes the transition speed change as it moves (functions may be cubic, quartic, etc)
420
429
Here we see ` quartic-in-out `
421
430
422
431
``` {r}
@@ -464,7 +473,7 @@ animate(animp, fps = 10, duration = 20)
464
473
465
474
```
466
475
467
- ## Transition Options: Timing
476
+ ## How Fast Things Move ( Timing)
468
477
469
478
In addition to entry, exit, and transition easing:
470
479
@@ -490,7 +499,7 @@ animp <- baseplot3 +
490
499
```
491
500
492
501
493
- ## Set Timings - Render
502
+ ## Set Timings
494
503
495
504
Slower pace feels smoother, and doesn't insinuate that the last frame and the first flow into each other
496
505
@@ -500,18 +509,24 @@ animate(animp, fps = 10, duration = 20)
500
509
501
510
```
502
511
503
- ## Transition States - What Does It Do? {.smaller}
512
+ ## Transition States Drilldown
513
+
514
+ <!-- {.smaller} -->
515
+
516
+
517
+ <div class =" columns-2 " >
504
518
505
519
``` {r, eval=FALSE}
506
520
transition_states(
507
- X_date_year,
521
+ states = X_date_year,
508
522
transition_length = 5,
509
523
state_length = c(rep(.25, 21), 20),
510
524
wrap = FALSE)+
511
525
512
526
```
513
527
514
- Assign the state unit - here we use the year.
528
+
529
+ ** States** : Assign the state unit - here we use the year.
515
530
516
531
** Transition length**
517
532
@@ -523,7 +538,8 @@ Assign the state unit - here we use the year.
523
538
- period of time where the state stays static
524
539
- here I am making the very last state stay static longer
525
540
526
- ** Wrap** determines whether to apply transition smoothing between the end and restarting
541
+ ** Wrap** : determine whether to apply transition smoothing between the end and restarting
542
+ <BR >
527
543
Experiment with these settings to get the look you want!
528
544
529
545
0 commit comments