class: title-slide
# Introduction ## Data processing with the tidyverse .center[<img src="img/00/logo-rworkshop.png" width="100px"/>] ### A. Ginolhac | rworkshop | 2021-09-08 --- class: middle # Good morning! ### What you can do now: .pull-left[ #### Check the material at the main site .Large[https://rtidyverse2021.leibniz-psychology.org/] #### Info and schedule .Large[https://leibniz-psychology.org/rtidyverse2021/] ].pull-right[ #### Check your install .large[https://rtidyverse2021.leibniz-psychology.org/install_tutorial.html] <img src="lecture01_intro_files/figure-html/unnamed-chunk-1-1.png" width="504" /> ] --- # Overview
.large[ This 3-day-course provides an introduction to the **tidyverse**, a
dialect. - Focusing on loading and cleaning data for exploratory visualizations - Speeding data manipulation is the mission of this course - This workshop is composed of 30 hours: ] .flex[ .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mr1[ .large[.gbox[Lectures]] - ~ 8 hours - available online (
/
) - live **exercises** included ] .w-50.bg-washed-blue.b--blue.ba.bw2.br3.shadow-5.ph3.ml1[ .large[.bbox[Practicals]] - ~ 15 hours - Using your own laptop - Supplementary exercises if needed ] ] --- class: vs1 # Speakers .center[] --- # Learning objectives .flex[ .w-50.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.ml6[ .large[.gbox[You will learn]] .float-img[] .Large[ -
specificity + community + package ecosystem + vectorization - opinionated tidyverse - Rstudio layout - basic data types (recap) - basic data structures (recap) ] ] ] --- # What is R?
.Large[
is shorthand for ["GNU R"](https://www.r-project.org): - An **interactive** programming language derived from **S** (**J. Chambers**, Bell Lab, 1976) - Appeared in 1993, created by **R. Ihaka** and **R. Gentleman**, University of Auckland, NZ - Focus on data analysis and plotting -
is also shorthand for the ecosystem around this language + Book authors + Package developers + Ordinary useRs Learning to use
will make you **more efficient** and **facilitate the use** of advanced data analysis tools ] --- # Why using R?
.Large[ - It's *free!* and **open-source** - easy to install / maintain - multi-platform (Windows, macOS, GNU/Linux) - can process big files and analyse huge amounts of data (db tools) - integrated data visualization tools, *even dynamic* [`shiny`](https://shiny.rstudio.com/) - fast, and even faster with *C++* integration via [Rcpp](http://dirk.eddelbuettel.com/code/rcpp/Rcpp-attributes.pdf) or [cpp11](https://cpp11.r-lib.org/). - easy to get help + [huge R community in the web](https://support.rstudio.com/hc/en-us/articles/200552336-Getting-Help-with-R) + [stackoverflow](http://stackoverflow.com/questions/tagged/r) with a lot of tags like **r**, **ggplot2** etc. + [rbloggers](http://www.r-bloggers.com) ] --- # About R is slow .center[] .footnote[Source: [Jozef Hajnala](https://jozef.io/r921-happy-birthday-r/)] --- # Twitter R community .large[[`#rstats`](https://twitter.com/search?q=%23rstats) on twitter] .center[] --- # Constant trend .pull-left[ .footnote[Source: [Touchon & McCoy. _Ecosphere_. 2016](http://onlinelibrary.wiley.com/doi/10.1002/ecs2.1394/full)] ] .pull-right[  .footnote[Source: [D. Robinson, StackOverflow blog](https://stackoverflow.blog/2017/10/10/impressive-growth-r/)] ] --- # Packages .center[] .footnote[Source: [rdrr.io](https://rdrr.io/) on 2021-05-04] .flex[ .w-33.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .Large[.wbox[[CRAN](https://cran.r-project.org/web/packages/available_packages_by_date.html)]] .large[**reliable**]: package is checked during submission process [MRAN](https://mran.microsoft.com/packages/) for Windows users ] .w-33.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[[bioconductor](https://www.bioconductor.org/)]] - dedicated to biology. [{limma} example](https://www.bioconductor.org/packages/release/bioc/html/limma.html) - required dedicated package typical install: ```r # install.packages("BiocManager") BiocManager::install("limma") ``` ] .w-33.bg-washed-red.b--red.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.wbox[[GitHub](https://github.com/)]] easy install thanks to [remotes](https://remotes.r-lib.org/). ```r # install.packages("remotes") remotes::install_github("tidyverse/readr") ``` could be a security issue ]] --- class: hide_logo # [R-universe](https://r-universe.dev/) - [ropensci](https://ropensci.or) initiative, by [Jeroen Ooms](https://ropensci.org/author/jeroen-ooms/) - [Video intro](https://ropensci.org/commcalls/may2021-r-universe/), everyone can have a domain for publishing their content - Provides automated built vignettes and binary packages for
/
(also dev versions) - No `remotes` / `devtools` / `rtools` required, design your rules outside **CRAN** .center[ [](https://gadenbuie.r-universe.dev/ui#builds) ] --- # Installation .pull-left[ .bold[CRAN] install from Rstudio (autocompletion)  ] .pull-right[ .bold[CRAN] install from Rstudio' console  ] .footnote[more in the article from [David Smith](http://blog.revolutionanalytics.com/2017/01/cran-10000.html)] --- # Help pages .pull-left[ 2 possibilities for manual pages. ```r ?log help(log) ``` Sadly, manpages are often unhelpful, **vignettes** or [**articles**](http://readxl.tidyverse.org/articles/sheet-geometry.html) better described workflow. ] .pull-right[ In **Rstudio**, the help page can be viewed in the bottom right pane  ] --- # Drawback: Steep learning curve ### Period of much suckiness .vembedr[
] --- class: middle, center .huge[ >The bad news is that when ever you learn a new skill you’re going to _suck_. It’s going to be _frustrating_. The .green.bold[good] news is that is .bold[typical] and happens to .bold[everyone] and it is only .bold[temporary]. You can’t go from knowing nothing to becoming an expert without going through a period of great _frustration_ and great _suckiness_. .tr[ — _Hadley Wickham_] ] .footnote[source: [Hadley Wickham dplyr tutorial at useR 2014](https://youtu.be/8SGif63VW6E?t=252)] --- # R is hard to learn .Large[**R base** is complex, has a long history and many contributors] .flex[ .w-70.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph4.ml6[ .large[.gbox[Why R is hard to learn]] - Unhelpful help `?print` - generic methods `print.data.frame` - too many commands `colnames, names` - inconsistent names `read.csv, load, readRDS` - un-strict syntax, was designed for interactive usage - too many ways to select variables `df$x, df$"x", df[,"x"], df[[1]]` - [...] see [r4stats' post](http://r4stats.com/articles/why-r-is-hard-to-learn/) for the full list - the `tidyverse` curse ]] -- .flex[ .w-70.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph2.mt2.ml6[ > Navigating the balance between `base` R and the `tidyverse` is a challenge to learn .tr[ — _Robert A. Muenchen_] ] ] .center[.footnote[source: [Robert A. Muenchen' blog](http://r4stats.com/articles/why-r-is-hard-to-learn/)]] --- class: middle, center
.Large[ >The ambiguity [of the S language] is real and goes to a key objective: we wanted users to be able to begin in an .bold.red[interactive environment], where they did not consciously think of themselves as programming. Then as their needs became clearer and their sophistication increased, they should be able .blue.bold[slide gradually into programming], when the language and system aspects would become more important. .tr[ — _John Chambers, "Stages in the Evolution of S"_] ] .footnote[source: [Teaching R to New Users: from tapply to Tydiverse 2018](https://www.youtube.com/watch?v=5033jBHFiHE) by .bold[Roger D. Peng]] --- ## Tidyverse origin
.left-column[ .Large[H. Wickham] [Hadley](http://had.co.nz) is Chief Scientist at **Rstudio** - coined the _tidyverse_ at [userR meeting in 2016](https://twitter.com/drob/status/748196885307920385) - developed and maintains most of the core _tidyverse_ packages  ] .right-column[ .Large[ We think the [**tidyverse**](http://tidyverse.org/) is better, especially for beginners. It is: - recent (both an issue and an advantage) - allows [doing powerful things quickly](http://varianceexplained.org/r/teach-tidyverse/) - unified - consistent, one way to do things - give strength to learn base R - criticisms will come later ]] --- ## Tidyverse, core packages .center[] --- # Top download .center[<img src="img/intro_top_download_metacran_2020-11-09.png", width="55%">] .left[.footnote[source: [METACRAN, top downloaded](https://www.r-pkg.org/downloaded) (2020-11-09)]] --- # Rstudio / tidyverse hard to ignore .center[<img src="img/intro_top_download_metacran_2020-11-09_tv.png", width="55%">] .left[.footnote[source: [METACRAN, top downloaded](https://www.r-pkg.org/downloaded) (2020-11-09)]] --- # 18<sup>th</sup> of May, R 4.1 .pull-left[ ### Tidyverse .huge[ - pipe
- lambda: `~ .x` ] .large[ - `c(factor("a"), factor("b"))` is `[1] a b`
] ] .footnote[[lambda](https://en.wikipedia.org/wiki/Anonymous_function) functions are .bold[anonymous]. Classic syntax is `(function(x) x + 2)(2)` </br>.bold[v4.0] brought `stringsAsFactors = FALSE` that `tibbles` have] -- .pull-right[ ###
v4.1 .huge[ - native pipe `|>` - lambda: `\(x)` - combine factors also works (before: `[1] 1 1`) ] ] --- class: inverse, center, middle  --- # What is it? .Large[[RStudio](https://www.rstudio.com/products/RStudio/)] is an Integrated Development Environment It makes working with R much easier .left-column[ ## .red[Warning] .large[Don't mix up **R** and **RStudio**. **R** needs to be installed first.] ] .right-column[ ## Features .large[ - _Projects_ to ease files organisation - _Console_ to run **R**, with syntax highlighter - full support for _Rmarkdown_ docs & chunks - _Viewer_ for data / plots / website - _Package management_ (including building, tests and development) - _Autocompletion_ using <kbd>TAB</kbd> - [_Cheatsheets_](https://www.rstudio.com/resources/cheatsheets/) (**New** [2021-08-23](https://blog.rstudio.com/2021/08/23/cheat-sheet-updates/)) - _Git_ integration for versioning - _Inline_ outputs - _Keyboard shortcuts_ - integrated _Terminal_ - _Jobs_ for running long runs in a separated session ]] --- # The 4 panels layout .center[] --- # Four panels .pull-left[ ### scripting - could be your main window - should be a **Rmarkdown** doc - tabs are great ### Console - could be hidden with **inline** outputs - `Rmarkdown` output logs - optional, embed a nice `Terminal` tab - optional,`Jobs` tab ] .pull-right[ ### Environment - **Environment**, display loaded objects and their `str()` - History is useless IMO - nice `git` integration - **Build** for development - database **connections** interface - **Tutorial** integration of [`learnr`](https://rstudio.github.io/learnr/) ### Files / Plots / Help - **Packages** management tab - unnecessary **Plots** panel when using **inline** outputs - **Help** tab - Viewer for animations ] --- class: hide_logo # Rearrange panels  .footnote[[source:Shannon Pileggi](https://www.pipinghotdata.com/posts/2020-09-07-introducing-the-rstudio-ide-and-r-markdown/#rmd)] --- class: hide_logo # For reproducibility #### .green[Options to activate / deactivate] .pull-left[  ] .pull-right[ `rm(list = ls())` is not recommended - does **not** make a fresh R session + `library()` calls remain + working directory not set! + modified functions, [evil](https://github.com/romainfrancois/evil.R) `==` <- `!=` - knitting `Rmarkdown` files solves it .footnote[[source: Jenny Bryan article](https://www.tidyverse.org/articles/2017/12/workflow-vs-script/)] ] --- # Code diagnostics, highly recommended using `Global Options -> Code -> Diagnostics` editing panel: .pull-left[  .bottom-footnote[source: [Kevin Ushey' article](https://support.rstudio.com/hc/en-us/articles/205753617-Code-Diagnostics?version=1.1.133&mode=desktop)] ] .pull-right[ - check argument calls  - missing arguments  - variable definitions  + unused variables & style recommendations ] --- # Symbol and their names for this course .flex[ .w-70.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph2.mt2.mr3[ .bbox[Common operators] .large[ `=` - equal `.` - dot `,` - comma `>` - greater than `<` - less than `~` - twiddle `*` - star `-` - hyphen `_` - underscore ]] .w-70.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph2.mt2.mr3[ .bbox[Quotation and comments] .large[ `"` - double quotation marks `'` - single quotation marks `` ` `` - backticks `#` - hash <code>|</code> - (vertical) bar `/` - (forward) slash `\` - backslash ] ] .w-70.bg-washed-yellow.b--yellow.ba.bw2.br3.shadow-5.ph2.mt2[ .bbox[Enclosures] .large[ `()` - parentheses `[]`- (square) brackets `{}` - (curly) braces `<>` - chevrons ] .bbox[R-specific operators] .large[ `<-` - assignment (left) `->` - right assignment `%>%` - (magrittr) pipe `|>` - (base) pipe ] ] ] --- ## Arithmetic operations .large[ .pull-left[ - `+`: addition - `-`: subtraction - `*`: multiplication - `/`: division - `^` or `**`: exponentiation - `%%`: modulo (remainder after division) - `%/%`: integer division ] .pull-right[ #### **Remember** that **R** will: - first perform **exponentiation** - then multiplications and/or divisions - and finally additions and/or subtractions. ### prioritization change the priority in evaluation: - parentheses `(` and `)` to group calculations ] ] --- ## Using `library()`, ensure function' origin .pull-left[ with only `base` loaded ```r x <- 1:10 filter(x, rep(1, 3)) ``` ``` Time Series: Start = 1 End = 10 Frequency = 1 [1] NA 6 9 12 15 18 21 24 27 NA ``` ] .pull-right[ .bold.red[Conflict]: 2 packages export same function with the same name, the latest loaded wins ```r library(dplyr) filter(x, rep(1, 3)) ``` ``` Error in UseMethod("filter"): no applicable method for 'filter' applied to an object of class "c('integer', 'numeric')" ``` **Solution**: use `::` to call functions from a specific package ```r stats::filter(x, rep(1, 3)) ``` ``` Time Series: Start = 1 End = 10 Frequency = 1 [1] NA 6 9 12 15 18 21 24 27 NA ``` Or use the [`conflicted`](https://github.com/r-lib/conflicted) package ] --- class: inverse, middle, center # Data types and structures ## R base --- # Getting started Let's get ready to use **R** and **RStudio** .flex[ .w-70.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.ml5[ .large[.gbox[do the following]] - Open up RStudio - Maximize the RStudio window - Click the Console pane, at the prompt (`>`) type in `3 + 2` and hit enter ```r > 3 + 2 ``` ]] --- # 4 main types .pull-left[
Type
Example
numeric
integer (2), double (2.34)
character (strings)
'tidyverse!'
boolean
TRUE / FALSE
complex
2+0i
### Missing data and special cases ```r NA # not available, missing data NA_real_ NA_integer_ NA_character_ NA_complex_ NULL # empty -Inf/Inf # infinite values NaN # Not a Number ``` ] -- .pull-right[ ```r 2L ``` ``` [1] 2 ``` ```r typeof(2L) ``` ``` [1] "integer" ``` ```r 2.34 ``` ``` [1] 2.34 ``` ```r typeof(2.34) ``` ``` [1] "double" ``` ```r "tidyverse!" ``` ``` [1] "tidyverse!" ``` ```r TRUE ``` ``` [1] TRUE ``` ```r 2+0i ``` ``` [1] 2+0i ``` ] --- # Structures .pull-left[ ### Vectors `c()` is the function for **concatenate** ```r 4 ``` ``` [1] 4 ``` ```r c(43, 5.6, 2.90) ``` ``` [1] 43.0 5.6 2.9 ``` ### Factors convert strings to factors, `levels` is the dictionary ```r factor(c("AA", "BB", "AA", "CC")) ``` ``` [1] AA BB AA CC Levels: AA BB CC ``` ] .pull-right[ ### Lists very important as it can contain .Large[anything] ```r list(f = factor(c("AA", "AA")), v = c(43, 5.6, 2.90), s = 4L) ``` ``` $f [1] AA AA Levels: AA $v [1] 43.0 5.6 2.9 $s [1] 4 ``` ] --- ## Data frames are special lists .pull-left[ ### `data.frame` same as list **but** where all objects _must_ have the **same** length ```r data.frame( f = factor(c("AA", "AA", "BB")), v = c(43, 5.6, 2.90), s = rep(4, 3)) ``` ``` f v s 1 AA 43.0 4 2 AA 5.6 4 3 BB 2.9 4 ``` ] .pull-right[ ### Example, missing one element in `v` ```r data.frame( f = factor(c("AA", "AA", "BB")), v = c(43, 5.6), s = rep(4, 3)) ``` ``` Error in data.frame(f = factor(c("AA", "AA", "BB")), v = c(43, 5.6), s = rep(4, : arguments imply differing number of rows: 3, 2 ``` ] --- ## Concatenate atomic elements .pull-left[ ### collection of simple _things_ - _things_ are the smallest elements: **atomic** - **must** be of same **mode**: .red.bold[automatic] coercion - indexed, from **1** to `length(vector)` - created with the **`c()`** function ```r c(2, TRUE, "a string") ``` ``` [1] "2" "TRUE" "a string" ``` ] -- .pull-right[ #### Manual coercion ```r as.character(c(2, TRUE, "a string")) ``` ``` [1] "2" "TRUE" "a string" ``` ```r as.double(c(2, TRUE, "a string")) ``` ``` [1] 2 NA NA ``` ```r as.double(c(2, 2.456, "a string")) ``` ``` [1] 2.000 2.456 NA ``` ] --- ## Assignment .large[operator is `<-`, associate a _name_ to an object] .pull-left[ ```r my_vec <- c(3, 4, 1:3) my_vec ``` ``` [1] 3 4 1 2 3 ``` .flex[ .w-80.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.gbox[tip]] Rstudio has the built-in shortcut <kbd>Alt</kbd>+<kbd>-</kbd> for `<-` ] ] ] .pull-right[ ### Rationale .large[ if you don't assigned a name to a created object it is only temporary. Assigning allows to save and re-use the object for a downstream step.] ] --- class: hide_logo # Binding names to values .pull-left[ ### Object has no name <blockquote class="twitter-tweet"><p lang="en" dir="ltr">In <a href="https://twitter.com/hashtag/rstats?src=hash&ref_src=twsrc%5Etfw">#rstats</a>, it's surprisingly important to realise that names have objects; objects don't have names <a href="https://t.co/bEMO1YVZX0">pic.twitter.com/bEMO1YVZX0</a></p>— Hadley Wickham (@hadleywickham) <a href="https://twitter.com/hadleywickham/status/732288980549390336?ref_src=twsrc%5Etfw">May 16, 2016</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> ] -- .pull-right[ #### vector is bind to the name `x` ```r x <- 1:3 ```  ####same vector is also bind to the name `y` ```r y <- x ```  .footnote[source: **H. Wickham** - [Adv _R_](https://adv-r.hadley.nz/names-values.html), [licence CC](http://creativecommons.org/licenses/by-nc-nd/3.0/us/)] ] --- # Hierarchy .pull-left[ .center[] ] .footnote[source: **H. Wickham** - [_R_ for data science](http://r4ds.had.co.nz/vectors.html), [licence CC](http://creativecommons.org/licenses/by-nc-nd/3.0/us/)] .pull-right[ ```r is.vector(c("a", "c")) ``` ``` [1] TRUE ``` ```r is.vector(list(a = 1)) ``` ``` [1] TRUE ``` ```r is.atomic(list(a = 1)) ``` ``` [1] FALSE ``` ```r is.data.frame(list(a = 1)) ``` ``` [1] FALSE ``` ] --- # Subsetting vectors .flex[ .w-30.bg-washed-red.b--red.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large[.rbox[important
]] .center.large[ unlike **python** or **Perl**, vectors use **1-based** index!! ] ] .w-33.bg-green-red.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large.ybox[.Large[`:`] operator] generate integer sequence ```r 3:10 ``` ``` [1] 3 4 5 6 7 8 9 10 ``` ] .w-33.bg-washed-gren.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ .large.ybox[extract > 1 element] select elements from position **3** to **10**: ```r LETTERS[3:10] ``` ``` [1] "C" "D" "E" "F" "G" "H" "I" "J" ``` ]] -- .flex[ .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1.ml6[ .large.ybox[break in sequence, use `c()`] ```r LETTERS[c(2:5, 7)] ``` ``` [1] "B" "C" "D" "E" "G" ``` ] .w-30.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr6[ .large.ybox[negative selection] ```r LETTERS[-(2:21)] ``` ``` [1] "A" "V" "W" "X" "Y" "Z" ``` ]] --- class: slide-practical ## Vectorized operation, one of the best R feature
02
:
00
.flex[ .w-33.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ ```r my_vec <- 1:8 my_vec ``` ``` [1] 1 2 3 4 5 6 7 8 ``` ```r my_vec + 2 ``` ``` [1] 3 4 5 6 7 8 9 10 ``` ] .w-33.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ #### try this one ```r my_vec / 2 ``` ] .w-33.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt3.mr1[ #### and this one, how does it work? ```r my_vec + 1:4 ``` ]] --- ## Answers .pull-left[ .flex[ .w-100.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph1.mt3.mr1[ ```r my_vec / 2 ``` ``` [1] 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 ``` ```r my_vec + 1:4 ``` ``` [1] 2 4 6 8 6 8 10 12 ``` .Large[`R`] is .bold[recycling] (*silently*) the shorter vector. .bold[But], incompatible lengths create a *warning* ! ```r my_vec + 1:3 ``` ``` Warning in my_vec + 1:3: longer object length is not a multiple of shorter object length ``` ``` [1] 2 4 6 5 7 9 8 10 ``` ] ] ] -- .pull-right[ .flex[ .w-100.bg-washed-red.b--red.ba.bw2.br3.shadow-5.ph1.mt3.mr1[ #### Avoid writing loops (and do .red[not] grow a vector) ```r res <- vector(mode = "numeric", length = length(my_vec)) for (i in seq_along(my_vec)) { res[i] <- my_vec[i] + 2 } res ``` ``` [1] 3 4 5 6 7 8 9 10 ``` ] ] ] --- ## Pipes ### Output the result of one function as input for the next one
.pull-left[ #### .Large[R base], classic parenthesis syntax ```r set.seed(12) round(mean(rnorm(5)), 2) ``` ``` [1] -0.76 ``` And pipes are into .large.bold[R base] since version .bold[4.1] as .large[`|>`]*. For **tidyverse** functions (`data` first argument), both pipes work similarly. Base being faster. .footnote[*: [Luke Tierney useR!2020](https://youtu.be/X_eDHNVceCU?t=4084)] ] .pull-right[ ####.Large[[`magrittr`](https://cran.r-project.org/web/packages/magrittr/vignettes/magrittr.html)] pipeline, (originally by Stefan M. Bache) ```r set.seed(12) rnorm(5) %>% mean() %>% round(2) ``` ``` [1] -0.76 ``` Of note, `magrittr` needs to loaded with either: ```r library(magrittr) library(dplyr) library(tidyverse) ``` ] --- ## Before we stop .flex[ .w-60.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt2.ml1[ .large[.gbox[You learned to:] .float-img[] - Introduction + R + Rstudio + tidyverse rationale - data types + main categories + coerce - data structures + main categories + sub-setting + vectorization ] ] .w-40.bg-washed-green.b--green.ba.bw2.br3.shadow-5.ph3.mt2.ml2[ .large[.bbox[Acknowledgments 🙏 👏]] * Roland Krause * Hadley Wickham * Robert Muenchen * Romain François * Jenny Bryan ]] .w-60.pv2.ph3.mt1.ml6[ .huge[.bbox[Thank you for your attention!]] ]