PageSourceSearch

https://tsggplot.netlify.app/

html tsggplot.netlify.app collected 2026-10-03 11:32:25 UTC 15,263 bytes, 522 lines download raw bytes

1<!DOCTYPE html>
2<html lang="" xml:lang="">
3  <head>
4    <title>Visualing Time Series</title>
5    <meta charset="utf-8" />
6    <meta name="author" content="Tatjana Kecojevic" />
7    <meta name="date" content="2020-05-07" />
8    <link href="libs/remark-css/default.css" rel="stylesheet" />
9    <link href="libs/font-awesome/css/fontawesome-all.min.css" rel="stylesheet" />
10    <link rel="stylesheet" href="assets/css/my-theme.css" type="text/css" />
11    <link rel="stylesheet" href="assets/css/my-fonts.css" type="text/css" />
12    <link rel="stylesheet" href="columns.css" type="text/css" />
13  </head>
14  <body>
15    <textarea id="source">
16
17
18
19
20layout: true
21
22&lt;a class="footer-link" href="https://sisteranalyst.org"&gt;sisteranalyst.org&lt;/a&gt;
23
24---
25
26class: title-slide, center, bottom
27
28# Visualing Time Series
29
30## Data Literacy in R
31
32### Tatjana Kecojevic
33
34---
35
36class: freight-slide, center, middle, inverse
37
38# .shadow-text[ecdc's covid-19 data]
39
40**Covid-19 data** is a set of deily observations on the number of newly infected and death cases in different countries around the world.
41
42## .emphasis[&lt;https://www.ecdc.europa.eu/en/publications-data&gt;]
43
44---
45# .shadow-text[Grammar of Graphics]
46
47The [grammar of graphics](http://vita.had.co.nz/papers/layered-grammar.html) enables a structured way of creating a plot by adding the components as layers, making it look effective and attractive.
48
49- data
50- aesthetic mapping
51- geometric object
52- statistical transformations
53- scales
54- coordinate system
55- position adjustments
56- faceting
57
58Imagine talking about baking a cake and adding a cherry on the top. 🎂🍒 This philosophy has been built into the [`ggplot`](https://ggplot2.tidyverse.org/reference/) package by [Hadley Wickham](http://hadley.nz) for creating elegant and complex plots in R.
59
60---
61# .shadow-text[Build a plot layer by layer]
62
63Built up on the 'Grammar of Graphics' philosophy the [`ggplot2`](https://cran.r-project.org/web/packages/ggplot2/index.html) package enables you to construct complex plot by iteration of discrete layers. It allows for the layers with different data sets and aesthetic mapping to be put together to create sophisticated plots at a high level of abstraction that encapsulate data from multiple sources.   
64
65All **ggplot2 plots** begin with a call to `ggplot()`, supplying default data and aesthethic mappings, specified by aes(). You then add layers, scales, coords and facets with `+`.
66
67To explore and learn more:
68
69- [ggplot cheatsheet](https://rstudio.com/wp-content/uploads/2015/03/ggplot2-cheatsheet.pdf)
70- [reference: layers](https://ggplot2.tidyverse.org/reference/)
71
72.footnote[
73💡 [ggplot2](https://ggplot2.tidyverse.org/) is a part of the [tidyverse](https://www.tidyverse.org/), an ecosystem of packages designed with common APIs and a shared philosophy. 
74]
75
76---
77# What we need to do
78
79The best way to master it is by practising. So let us create an awesome `ggplot`. 😃
80What we need to do is the following:
81
82**i.** Read [covid-19](https://en.wikipedia.org/wiki/COVID-19_pandemic) [ecdc](https://www.ecdc.europa.eu/en/publications-data) data 
83
84**ii.** Wrangle the data in the format suitable for visualisation.
85
86**iii.** "Initialise" a plot with `ggplot()`:
87  
88**ggplot(&lt;span style="color:blue"&gt;dataframe&lt;/span&gt;, aes(&lt;span style="color:orangered"&gt;x = explanatory variable&lt;/span&gt;, &lt;span style="color:green"&gt;y = response variable&lt;/span&gt;))**
89
90and add a few layers to make it informative and captivating.
91
92---
93name: astroboy
94background-image: url(images/astro_boy.jpg)
95background-size: contain
96background-color: #f6f6f6
97
98
99# .emphasis[packages to install and upload]
100
101##### `install.packages("readxl")`
102##### `install.packages("httr")`
103##### `install.packages("lubridate")`
104##### `install.packages("tidyr")`
105##### `install.packages("ggplot2")`
106##### `install.packages("dplyr")`
107
108.footnote[
109💡 Check the list of the packages assembeld into the [tidyverse](https://www.tidyverse.org/packages/).
110]
111---
112## **Task 1:** Get **ecdc** data
113
114
115```r
116library(readxl)
117library(httr)
118library(lubridate)
119library(tidyr)
120library(ggplot2)
121library(dplyr)
122# access ecdc data
123url2 &lt;- "https://www.ecdc.europa.eu/sites/default/files/documents/COVID-19-geographic-disbtribution-worldwide-2020-05-06.xlsx"
124GET(url2, write_disk(tf &lt;- tempfile(fileext = ".xlsx")))
125covid_ecdc &lt;- read_excel(tf)
126```
127.footnote[
128💡 Check &lt;https://importdata2r.netlify.app&gt; to learn how to read data in R.
129]
130
131---
132## Create ex-YU data subset
133
134
135```r
136covid_yu &lt;- covid_ecdc %&gt;% 
137  filter(countriesAndTerritories %in% c("Bosnia_and_Herzegovina", 
138                                        "Croatia", 
139                                        "Montenegro", 
140                                        "North_Macedonia", 
141                                        "Serbia", 
142                                        "Slovenia"))
143# remove unneeded columns
144covid_yu &lt;- covid_yu[, -c(2:4, 8)]
145```
146---
147## **Task 2:** Data Wrangling
148
149
150```r
151covid_yu &lt;- covid_yu %&gt;% 
152  separate(dateRep, c("dateRep"), sep = "T") %&gt;%
153  group_by(countriesAndTerritories) %&gt;% 
154  arrange(dateRep) %&gt;% 
155  mutate(total_cases = cumsum(cases), 
156         total_deaths = cumsum(deaths)) %&gt;% # cumulative data
157  mutate(Diff_cases = total_cases - lag(total_cases), 
158         Rate_pc_cases = round(Diff_cases/lag(total_cases) * 100, 2)) %&gt;% # growt rate
159  mutate(second_der = Diff_cases - lag(Diff_cases)) %&gt;% # 2nd derivative
160  rename(country = countriesAndTerritories) %&gt;% 
161  rename(country_code = countryterritoryCode)
162covid_yu$dateRep &lt;- as.Date(covid_yu$dateRep) # set `dateRep` as date type  
163covid_sr &lt;- covid_yu %&gt;% 
164  filter(country_code == "SRB") # subset SRB data
165```
166
167
168---
169## **Task 3:** ggplot: `\(F^{''}(x)\)` vs date of recording 
170
171.pull-left[
172
173```r
174covid_sr %&gt;% 
175  filter(!is.na(second_der)) %&gt;% 
176* ggplot(aes(x = dateRep, y = second_der))
177
178```
179
180]
181
182.pull-right[
183&lt;img src="images/ggplot1.png" width="726" /&gt;
184
185]
186
187---
188## add the time serie
189
190.pull-left[
191
192```r
193covid_sr %&gt;% 
194  filter(!is.na(second_der)) %&gt;% 
195  ggplot(aes(x = dateRep, y = second_der)) +
196* geom_line()
197```
198
199]
200
201.pull-right[
202&lt;img src="images/ggplot2.png" width="726" /&gt;
203
204]
205
206---
207## add data points
208
209.pull-left[
210
211```r
212covid_sr %&gt;% 
213  filter(!is.na(second_der)) %&gt;% 
214  ggplot(aes(x = dateRep, y = second_der)) +
215* geom_line() + geom_point(col = "#00688B")
216
217```
218
219]
220
221.pull-right[
222&lt;img src="images/ggplot3.png" width="726" /&gt;
223
224]
225
226---
227## remove axes labels
228
229.pull-left[
230
231```r
232covid_sr %&gt;% 
233  filter(!is.na(second_der)) %&gt;% 
234  ggplot(aes(x = dateRep, y = second_der)) +
235  geom_line() + geom_point(col = "#00688B") +
236* xlab("") + ylab("")
237
238```
239
240]
241
242.pull-right[
243&lt;img src="images/ggplot4.png" width="726" /&gt;
244
245]
246
247---
248## add title and caption
249
250.pull-left[
251
252```r
253covid_sr %&gt;% 
254  filter(!is.na(second_der)) %&gt;% 
255  ggplot(aes(x = dateRep, y = second_der)) +
256  geom_line() + geom_point(col = "#00688B") +
257  xlab("") + ylab("") +
258  labs (title = "2nd derivative of F(x)", 
259*       caption = "Data from: https://www.ecdc.europa.eu")
260
261```
262
263]
264
265.pull-right[
266&lt;img src="images/ggplot5.png" width="726" /&gt;
267
268]
269
270---
271##  use built-in [theme](https://ggplot2.tidyverse.org/reference/ggtheme.html)
272
273.pull-left[
274
275```r
276covid_sr %&gt;% 
277  filter(!is.na(second_der)) %&gt;% 
278  ggplot(aes(x = dateRep, y = second_der)) +
279  geom_line() + geom_point(col = "#00688B") +
280  xlab("") + ylab("") +
281  labs (title = "2nd derivative of F(x)", 
282        caption = "Data from: https://www.ecdc.europa.eu") +
283* theme_minimal()
284
285```
286
287]
288
289.pull-right[
290&lt;img src="images/ggplot6.png" width="726" /&gt;
291
292]
293
294---
295
296##  align title and remove grid lines
297
298.pull-left[
299
300```r
301covid_sr %&gt;% 
302  filter(!is.na(second_der)) %&gt;% 
303  ggplot(aes(x = dateRep, y = second_der)) +
304  geom_line() + geom_point(col = "#00688B") +
305  xlab("") + ylab("") +
306  labs (title = "2nd derivative of F(x)", 
307        caption = "Data from: https://www.ecdc.europa.eu") +
308  theme_minimal() +
309* theme(plot.title = element_text(size = 14, vjust = 2, hjust=0.5),
310*       panel.grid.major.x = element_blank(),
311*       panel.grid.minor.x = element_blank())
312
313```
314
315]
316
317.pull-right[
318&lt;img src="images/ggplot7.png" width="726" /&gt;
319
320]
321
322
323---
324
325## add vertical reference lines
326
327.pull-left[
328
329```r
330covid_sr %&gt;% 
331  filter(!is.na(second_der)) %&gt;% 
332  ggplot(aes(x = dateRep, y = second_der)) +
333  geom_line() + geom_point(col = "#00688B") +
334  xlab("") + ylab("") +
335  labs (title = "2nd derivative of F(x)", 
336        caption = "Data from: https://www.ecdc.europa.eu") +
337  theme_minimal() +
338  theme(plot.title = element_text(size = 14, vjust = 2, hjust=0.5),
339        panel.grid.major.x = element_blank(),
340        panel.grid.minor.x = element_blank()) +
341* geom_vline(xintercept = as.numeric(as.Date(c("2020-03-16", "2020-03-22", "2020-03-28", "2020-04-04", "2020-04-10", "2020-04-17", "2020-04-24", "2020-04-30"))), linetype=4, colour="red", alpha = 0.5)
342
343```
344
345]
346
347.pull-right[
348&lt;img src="images/ggplot8.png" width="660" /&gt;
349
350]
351
352---
353## anotate refrence lines with text
354
355.pull-left[
356
357```r
358ts_plot +
359*annotate(geom="text", x=as.Date("2020-03-16"), y = 150, label="state of\nemergency", col = "dodgerblue4") +
360* annotate(geom="text", x=as.Date("2020-03-22"), y = 70, label="curfew\n5pm-5am", col = "dodgerblue4") +
361* annotate(geom="text", x=as.Date("2020-03-28"), y = -140, label="weekend curfew\n3pm-5am", col = "dodgerblue4") +
362* annotate(geom="text", x=as.Date("2020-04-04"), y = 220, label="weekend curfew\n1pm Sat-5am Mon ", col = "dodgerblue4") +
363* annotate(geom="text", x=as.Date("2020-04-10"), y = -90, label="Easter curfew\n5pm Fri-5am Mon ", col = "dodgerblue4") +
364* annotate(geom="text", x=as.Date("2020-04-17"), y = 200, label="Easter curfew\n5pm Fri-5am Tue ", col = "dodgerblue4") +
365* annotate(geom="text", x=as.Date("2020-04-24"), y = -120, label="weekend curfew\n5pm Fri-5am Mon ", col = "dodgerblue4") +
366* annotate(geom="text", x=as.Date("2020-04-30"), y = 160, label="May Day curfew\n6pm Thu-5am Sat ", col = "dodgerblue4")
367```
368]
369
370.pull-right[
371&lt;img src="images/ggplot9.png" width="726" /&gt;
372
373]
374
375
376.footnote[
377💡 Note that the plot from the previous slide has been saved as `ts_plot`!
378]
379---
380name: astroboy
381background-image: url(images/ggplot9.png)
382background-size: contain
383background-color: #f6f6f6
384
385# .shadow-text[Nice... 😃]
386
387---
388class: freight-slide, center, middle, inverse
389
390# .shadow-text[To learn more visit: &lt;https://dataliteracy.rbind.io&gt;]
391
392.emphasis[To see it in action visit: &lt;http://covid19sr.rbind.io&gt;]
393
394[<i class="fab  fa-twitter "></i> @Tatjana_Kec](https://twitter.com/Tatjana_Kec)
395
396[<i class="fab  fa-github "></i> @TanjaKec](https://github.com/TanjaKec)
397    </textarea>
398<style data-target="print-only">@media screen {.remark-slide-container{display:block;}.remark-slide-scaler{box-shadow:none;}}</style>
399<script src="https://remarkjs.com/downloads/remark-latest.min.js"></script>
vendor: 1 bytes, line 399
399
400<script>var slideshow = remark.create({
401"highlightStyle": "solarized-light",
402"highlightLanguage": ["r", "css", "yaml"],
403"slideNumberFormat": "",
404"highlightLines": true,
405"countIncrementalSlides": false,
406"ratio": "16:9"
407});
408if (window.HTMLWidgets) slideshow.on('afterShowSlide', function (slide) {
409  window.dispatchEvent(new Event('resize'));
410});
411(function(d) {
412  var s = d.createElement("style"), r = d.querySelector(".remark-slide-scaler");
413  if (!r) return;
414  s.type = "text/css"; s.innerHTML = "@page {size: " + r.style.width + " " + r.style.height +"; }";
415  d.head.appendChild(s);
416})(document);
417
418(function(d) {
419  var el = d.getElementsByClassName("remark-slides-area");
420  if (!el) return;
421  var slide, slides = slideshow.getSlides(), els = el[0].children;
422  for (var i = 1; i < slides.length; i++) {
423    slide = slides[i];
424    if (slide.properties.continued === "true" || slide.properties.count === "false") {
425      els[i - 1].className += ' has-continuation';
426    }
427  }
428  var s = d.createElement("style");
429  s.type = "text/css"; s.innerHTML = "@media print { .has-continuation { display: none; } }";
430  d.head.appendChild(s);
431})(document);
432// delete the temporary CSS (for displaying all slides initially) when the user
433// starts to view slides
434(function() {
435  var deleted = false;
436  slideshow.on('beforeShowSlide', function(slide) {
437    if (deleted) return;
438    var sheets = document.styleSheets, node;
439    for (var i = 0; i < sheets.length; i++) {
440      node = sheets[i].ownerNode;
441      if (node.dataset["target"] !== "print-only") continue;
442      node.parentNode.removeChild(node);
443    }
444    deleted = true;
445  });
446})();
447(function() {
448  "use strict"
449  // Replace 
449<script> tags in slides area to make them executable
450  var scripts = document.querySelectorAll(
451    '.remark-slides-area .remark-slide-container script'
452  );
453  if (!scripts.length) return;
454  for (var i = 0; i < scripts.length; i++) {
455    var s = document.createElement('script');
456    var code = document.createTextNode(scripts[i].textContent);
457    s.appendChild(code);
458    var scriptAttrs = scripts[i].attributes;
459    for (var j = 0; j < scriptAttrs.length; j++) {
460      s.setAttribute(scriptAttrs[j].name, scriptAttrs[j].value);
461    }
462    scripts[i].parentElement.replaceChild(s, scripts[i]);
463  }
464})();
465(function() {
466  var links = document.getElementsByTagName('a');
467  for (var i = 0; i < links.length; i++) {
468    if (/^(https?:)?\/\//.test(links[i].getAttribute('href'))) {
469      links[i].target = '_blank';
470    }
471  }
472})();
473// adds .remark-code-has-line-highlighted class to <pre> parent elements
474// of code chunks containing highlighted lines with class .remark-code-line-highlighted
475(function(d) {
476  const hlines = d.querySelectorAll('.remark-code-line-highlighted');
477  const preParents = [];
478  const findPreParent = function(line, p = 0) {
479    if (p > 1) return null; // traverse up no further than grandparent
480    const el = line.parentElement;
481    return el.tagName === "PRE" ? el : findPreParent(el, ++p);
482  };
483
484  for (let line of hlines) {
485    let pre = findPreParent(line);
486    if (pre && !preParents.includes(pre)) preParents.push(pre);
487  }
488  preParents.forEach(p => p.classList.add("remark-code-has-line-highlighted"));
489})(document);</script>
489
490
491<script>
492slideshow._releaseMath = function(el) {
493  var i, text, code, codes = el.getElementsByTagName('code');
494  for (i = 0; i < codes.length;) {
495    code = codes[i];
496    if (code.parentNode.tagName !== 'PRE' && code.childElementCount === 0) {
497      text = code.textContent;
498      if (/^\\\((.|\s)+\\\)$/.test(text) || /^\\\[(.|\s)+\\\]$/.test(text) ||
499          /^\$\$(.|\s)+\$\$$/.test(text) ||
500          /^\\begin\{([^}]+)\}(.|\s)+\\end\{[^}]+\}$/.test(text)) {
501        code.outerHTML = code.innerHTML;  // remove <code></code>
502        continue;
503      }
504    }
505    i++;
506  }
507};
508slideshow._releaseMath(document);
509</script>
509
510<!-- dynamically load mathjax for compatibility with self-contained -->
511<script>
512(function () {
513  var script = document.createElement('script');
514  script.type = 'text/javascript';
515  script.src  = 'https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-MML-AM_CHTML';
516  if (location.protocol !== 'file:' && /^https?:/.test(script.src))
517    script.src  = script.src.replace(/^https?:/, '');
518  document.getElementsByTagName('head')[0].appendChild(script);
519})();
520</script>
520
521  </body>
522</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.