class: center, middle, inverse, title-slide .title[ # Good Code Practices ] .subtitle[ ## with a focus on R ] .author[ ### Chris Grandin and Andrew Edwards ] .institute[ ### Pacific Biological Station, Nanaimo, BC ] .date[ ### National TESA webinar. Slides compiled on 14 November, 2022. ] --- class: inverse center ### Pacific Biological Station, Nanaimo, B.C. {width=250px} --- class: left ### Motivation - Many of us are self-taught in computer coding - "When I wanted to become a marine biologist no-one told me I'd end up spending most of my time writing computer code" -- paraphrasing someone I saw on Twitter (I can't find the original tweet). -- - Probably all have some bad habits which we could get away with in the past - But now we share and collaborate on code a lot more (especially through GitHub) -- - bad habits can be annoying for collaborators -- - bad habits can be annoying for your future self -- - bad habits lead to wide eyes staring at space (E. Sheeran, respected programmer ) .pull-right[ <img src="img/ed.jpg" width="100" style="display: block; margin: auto;" /> ] --- class: left ### Motivation Things I figured out over the years - help others and your future self: README files and documenting code -- - setting up workflow (having organised folders) -- - defining variables just once in code -- - never use `T` and `F` for `TRUE` and `FALSE` -- took me a few hours of debugging once to learn this one the hard way -- - it is often worth simplifying some code to make it more efficient (not that I always do) -- - had previously thought you're fine to just use `=` instead of `<-`. Oops -- not any more (sorry!) -- - READ the error messages!! I thought of this while writing this talk, and not reading the error messages. -- - working closely with Chris on Pacific Hake stock assessment has helped my coding habits, so thought it worth him sharing some best practices -- - this is for TESA, and most stock assessment scientists are using R, so we'll focus on R, but some tips are applicable for other languages --- class: left ### Motivation - History and sociology of coding (though I didn't finish it) .pull-right[ <img src="img/coders-book-cover.jpg" width="250" style="display: block; margin: auto;" /> ] - Some good insights and tidbits - One Facebook engineer checked his contributions to the code - Added 391,973 lines -- - Removed 509,793 lines! -- - So on average he *removed* 39 lines of code per hour. -- - Common syndrome of people spending ages writing a program to automate a task rather than just "doing the damn thing itself". - One guy had to do some ONE-TIME cleaning up of data by hand. Should have taken half a day or so. -- - But he wanted to automate it. Took him two weeks, but was a useless tool. -- - So be careful sometimes. "Perfect is the enemy of good". --- class: center, middle, inverse ### On to the code... --- class: inverse background-image: url(img/obi-wan.jpg) background-size: contain <style type="text/css"> code.r{ /* Code block */ font-size: 10px; } h3{ margin-bottom: 0; padding: 0; } </style> --- class: center, middle, inverse # Compilation vs. Interpretation --- class: left ### Compilation vs Interpretation #### Compilation - A compiler takes some code written in a language and generates an executable file that can be run on a particular CPU - Compilation enforces strong typing which means you must define exactly what type a function's arguments must be and what type is returned - Examples of compiled languages are C++ and Fortran #### Interpretation - An interpreter **evaluates** code line-by-line at run time - Interpreted code is usually platform-independent / compiled code needs to be compiled for a specific CPU - Examples of interpreted languages are Python, Perl, Lisp, and R --- class: center, middle, inverse # Paths and file organization > "If the first line of your R script is" > > `setwd("C:\Users\me\path\only\I\have")` > > "I will come into your office and SET YOUR COMPUTER ON FIRE" > > "If the first line of your R script is" > > `rm(list = ls())` > > "I will come into your office and SET YOUR COMPUTER ON FIRE" > > <footer>- Jenny Bryan</footer> --- class: left ### Directory structure - using `here::here()` - To avoid this: 🔥 `setwd("C:\Users\me\path\only\I\have")` 🔥 - Make everything in your project relative to a root project directory - Use `here::here()` - Example: - If you have data in file called `mydata.csv` somewhere on your computer, create a `data` directory as a subdirectory of your project directory and place `mydata.csv` in there - *Anywhere* in your project code, reference that `data` directory like this: `here::here("data")` -- ```r message(getwd()) #> D:/github/main/good-code-practices/docs/presentation data_fn <- here::here("data", "mydata.csv") message(data_fn) #> D:/github/main/good-code-practices/data/mydata.csv d <- read.csv(data_fn) knitr::kable(d) ``` <table> <thead> <tr> <th style="text-align:right;"> Code </th> <th style="text-align:left;"> Species </th> <th style="text-align:left;"> Description </th> </tr> </thead> <tbody> <tr> <td style="text-align:right;"> 225 </td> <td style="text-align:left;"> Pacific hake </td> <td style="text-align:left;"> Great fish with lots of charisma </td> </tr> <tr> <td style="text-align:right;"> 614 </td> <td style="text-align:left;"> Pacific halibut </td> <td style="text-align:left;"> Big and tasty fish </td> </tr> </tbody> </table> --- class: left ### Directory structure - how `here::here()` works <img src="img/directory-structure-showing-here.jpg" width="300" style="display: block; margin: auto;" /> - If you want to see what the project's root directory is and why it was chosen, run the `here::dr_here()` function: ```r here::dr_here() #> here() starts at D:/github/main/good-code-practices. #> - This directory contains a file ".here" #> - Initial working directory: D:/github/main/good-code-practices/docs/presentation #> - Current working directory: D:/github/main/good-code-practices/docs/presentation ``` --- class: left ### Changing directories in code - Your code should *NEVER* contain the `setwd()` command. There's no need to change directories, ever. ```r message(getwd()) #> D:/github/main/good-code-practices/docs/presentation setwd("d:/github/main/good-code-practices/data") d <- read.csv("mydata.csv") message(getwd()) #> d:/github/main/good-code-practices/data ``` - It's a good bet that nobody else will be able to get the code to work. - the above code fails on Andy's computer with an error. - It probably won't work on your next machine either. - You have to manually navigate back to your project working directory if something breaks in your code 👊. - Instead do this: ```r message(getwd()) #> D:/github/main/good-code-practices/docs/presentation *d <- read.csv(here::here("data", "mydata.csv")) message(getwd()) #> D:/github/main/good-code-practices/docs/presentation ``` --- class: left ### Creating paths to directories and files - In Windows, don't use double-backslashes for paths, this removes platform-independence and R has evolved way past needing this. For example, you *can* define a path like this for Windows: ```r path <- "github\\main\\project" ``` - Instead, define it with forward slashes regardless of which OS you are on: ```r path <- "github/main/project" ``` - Or better yet, for complete platform-independence use `file.path()`: ```r file.path("github", "main", "project") #> [1] "github/main/project" ``` - Notice that that command has the same syntax as `here::here()`: ```r here::here("github", "main", "project") #> [1] "D:/github/main/good-code-practices/github/main/project" ``` --- class: left ### File naming standards - R code file names should end in .R - File should be named with small letters only with words separated by dashes or underscores. eg. `utilities.R`, `plot-biomass.R`, `table-decisions.R`, `load-model-files.R` - R source files should contain one function and the filename should be the same as the function name except with dashes as separators instead of underscores eg. file `plot-biomass.R` contains one function called `plot_biomass()` - Exceptions to the one-file-rule are files like `utilities.R` which have small utility functions that each fit on one screen .pull-left[ <img src="img/r-source-filenames.jpg" width="300" style="display: block; margin: auto;" /> ] .pull-right[ ```r vec2df <- function(vec, nms = NULL){ if(!is.null(nms) && length(vec) != length(nms)){ stop("The number of names supplied does not match the number ", "of elements in `vec`", call. = FALSE) names(df) <- nms } df <- vec |> enframe(name = NULL) |> t() |> as_tibble() if(!is.null(df)){ names(df) <- nms } df } ``` ] --- class: left ### Don't use `rm()` to *clear* the workspace, don't *save* the workspace - You might see `rm(list = ls(all.names = TRUE))` at the beginning of somebody's R script. It clears out all user-defined objects (including hidden) from the workspace - It is a sign that the person writing the code is *not sure* what variables their code is accessing. To remove doubt, they use this command to clear everything out - It doesn't start you with a *clean slate*. It leaves things: - Packages remain loaded - Options changed remain at their non-default values (`options()`) - If you are saving your workspace (.RData file) on closing, you are missing the point of using functionalized source code. Objects don't matter, code does. You should be able to re-recreate all objects from your source code - **To start with a brand new workspace, restart R**. In Rstudio it is Ctrl-Shift-F10. I do this very often, at least 10 times a day --- class: center, middle, inverse, bg_fir # Variable naming and organization > "There are only two hard things in Computer Science: cache invalidation and naming things." -- Phil Karlton > "There are only two hard things in Computer Science: cache invalidation, naming things, and off-by-one errors" -- Unknown --- class: left ### Variable naming standards - Standards apply to names for all functions, variables, and columns in data frames - Some different standards include: - flatcase - `spatialarea` (Java package names) - CapitalCamelCase - `SpatialArea` (C++ names, Java class names) - lowerCamelCase - `spatialArea` (Java variable names) - snake_case - `spatial_area` (Python variable names, R names) - UPPER_SNAKE_CASE - `SPATIAL_AREA` (Constants in many languages) - dotted.case - `spatial.area` (Some base R functions) - The worst thing to do is some combination of styles eg. `spatial_AREA.newvar` - Use **snake case** in R ```r model_fn_lst <- list() model_fn_lst$base_model <- here::here("models", "base-model", "base-model.rep") model_fn_lst$sens_model_1 <- here::here("models", "sens-models", "sens-model-1.rep") ``` --- class: left ### Base R has inconsistent naming - Base R functions use different standards including dotted, snake case, camel case, upper camel case, and flat case. These are sometimes even mixed up in a single function. - This is a major oversight and confusing for everyone, but it is legacy and they can't change it now. - One example is the `data.frame()` function which has arguments with two different types of naming syntax and some function calls inside with several different syntaxes - `anyDuplicated()` and `gettextf()`: -- ```r data.frame #> function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, #> fix.empty.names = TRUE, stringsAsFactors = FALSE) #> { #> data.row.names <- if (check.rows && is.null(row.names)) #> function(current, new, i) { #> if (is.character(current)) #> new <- as.character(new) #> if (is.character(new)) #> current <- as.character(current) #> if (anyDuplicated(new)) #> return(current) #> if (is.null(current)) #> return(new) #> if (all(current == new) || all(current == "")) #> return(new) #> stop(gettextf("mismatch of row names in arguments of 'data.frame', item %d", #> i), domain = NA) #> } #> else function(current, new, i) { #> if (is.null(current)) { #> if (anyDuplicated(new)) { #> warning(gettextf("some row.names duplicated: %s --> row.names NOT used", #> paste(which(duplicated(new)), collapse = ",")), #> domain = NA) #> current #> } #> else new #> } #> else current #> } #> object <- as.list(substitute(list(...)))[-1L] #> mirn <- missing(row.names) #> mrn <- is.null(row.names) #> x <- list(...) #> n <- length(x) #> if (n < 1L) { #> if (!mrn) { #> if (is.object(row.names) || !is.integer(row.names)) #> row.names <- as.character(row.names) #> if (anyNA(row.names)) #> stop("row names contain missing values") #> if (anyDuplicated(row.names)) #> stop(gettextf("duplicate row.names: %s", paste(unique(row.names[duplicated(row.names)]), #> collapse = ", ")), domain = NA) #> } #> else row.names <- integer() #> return(structure(list(), names = character(), row.names = row.names, #> class = "data.frame")) #> } #> vnames <- names(x) #> if (length(vnames) != n) #> vnames <- character(n) #> no.vn <- !nzchar(vnames) #> vlist <- vnames <- as.list(vnames) #> nrows <- ncols <- integer(n) #> for (i in seq_len(n)) { #> xi <- if (is.character(x[[i]]) || is.list(x[[i]])) #> as.data.frame(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) #> else as.data.frame(x[[i]], optional = TRUE) #> nrows[i] <- .row_names_info(xi) #> ncols[i] <- length(xi) #> namesi <- names(xi) #> if (ncols[i] > 1L) { #> if (length(namesi) == 0L) #> namesi <- seq_len(ncols[i]) #> vnames[[i]] <- if (no.vn[i]) #> namesi #> else paste(vnames[[i]], namesi, sep = ".") #> } #> else if (length(namesi)) { #> vnames[[i]] <- namesi #> } #> else if (fix.empty.names && no.vn[[i]]) { #> tmpname <- deparse(object[[i]], nlines = 1L)[1L] #> if (startsWith(tmpname, "I(") && endsWith(tmpname, #> ")")) { #> ntmpn <- nchar(tmpname, "c") #> tmpname <- substr(tmpname, 3L, ntmpn - 1L) #> } #> vnames[[i]] <- tmpname #> } #> if (mirn && nrows[i] > 0L) { #> rowsi <- attr(xi, "row.names") #> if (any(nzchar(rowsi))) #> row.names <- data.row.names(row.names, rowsi, #> i) #> } #> nrows[i] <- abs(nrows[i]) #> vlist[[i]] <- xi #> } #> nr <- max(nrows) #> for (i in seq_len(n)[nrows < nr]) { #> xi <- vlist[[i]] #> if (nrows[i] > 0L && (nr%%nrows[i] == 0L)) { #> xi <- unclass(xi) #> fixed <- TRUE #> for (j in seq_along(xi)) { #> xi1 <- xi[[j]] #> if (is.vector(xi1) || is.factor(xi1)) #> xi[[j]] <- rep(xi1, length.out = nr) #> else if (is.character(xi1) && inherits(xi1, "AsIs")) #> xi[[j]] <- structure(rep(xi1, length.out = nr), #> class = class(xi1)) #> else if (inherits(xi1, "Date") || inherits(xi1, #> "POSIXct")) #> xi[[j]] <- rep(xi1, length.out = nr) #> else { #> fixed <- FALSE #> break #> } #> } #> if (fixed) { #> vlist[[i]] <- xi #> next #> } #> } #> stop(gettextf("arguments imply differing number of rows: %s", #> paste(unique(nrows), collapse = ", ")), domain = NA) #> } #> value <- unlist(vlist, recursive = FALSE, use.names = FALSE) #> vnames <- as.character(unlist(vnames[ncols > 0L])) #> if (fix.empty.names && any(noname <- !nzchar(vnames))) #> vnames[noname] <- paste0("Var.", seq_along(vnames))[noname] #> if (check.names) { #> if (fix.empty.names) #> vnames <- make.names(vnames, unique = TRUE) #> else { #> nz <- nzchar(vnames) #> vnames[nz] <- make.names(vnames[nz], unique = TRUE) #> } #> } #> names(value) <- vnames #> if (!mrn) { #> if (length(row.names) == 1L && nr != 1L) { #> if (is.character(row.names)) #> row.names <- match(row.names, vnames, 0L) #> if (length(row.names) != 1L || row.names < 1L || #> row.names > length(vnames)) #> stop("'row.names' should specify one of the variables") #> i <- row.names #> row.names <- value[[i]] #> value <- value[-i] #> } #> else if (!is.null(row.names) && length(row.names) != #> nr) #> stop("row names supplied are of the wrong length") #> } #> else if (!is.null(row.names) && length(row.names) != nr) { #> warning("row names were found from a short variable and have been discarded") #> row.names <- NULL #> } #> class(value) <- "data.frame" #> if (is.null(row.names)) #> attr(value, "row.names") <- .set_row_names(nr) #> else { #> if (is.object(row.names) || !is.integer(row.names)) #> row.names <- as.character(row.names) #> if (anyNA(row.names)) #> stop("row names contain missing values") #> if (anyDuplicated(row.names)) #> stop(gettextf("duplicate row.names: %s", paste(unique(row.names[duplicated(row.names)]), #> collapse = ", ")), domain = NA) #> row.names(value) <- row.names #> } #> value #> } #> <bytecode: 0x000001b2c0124418> #> <environment: namespace:base> ``` --- class: left ### Don't use dotted names for variable names - If you come from other languages, the dot typically means that what is to the left is a class and what is to the right is a method of that class (C++, Java) so this is very confusing for those people. eg. in C++: `string.size()`, in Java: `Socket.connect()` - **Dotted syntax in R is meant to be used to signify the a method of a class.** eg. `plot.default()` -- .pull-left[.left[ ```r a <- 1:10 par(mar = c(2, 2, 0, 0)) plot(a, type = "l", lwd = 3, col = "blue") ``` ]] .pull-right[.left[ <img src="knitr-figs/plot-dotted-syntax-1.png" height="150" style="display: block; margin: auto;" /> ]] -- .pull-left[.left[ ```r a <- 1:10 *class(a) <- c(class(a), "revseries") *plot.revseries <- function(d, ...){ * plot.default(rev(d), ...) *} par(mar = c(2, 2, 0, 0)) plot(a, type = "l", lwd = 3, col = "blue") ``` ]] .pull-right[.left[ <img src="knitr-figs/plot-dotted-syntax-2-1.png" height="150" style="display: block; margin: auto;" /> ]] .pull-left[.left[ ```r class(a) #> [1] "integer" "revseries" ``` ]] --- class: center, middle, inverse # Standardizing your coding style > "Good coding style is like using correct punctuation. You can manage without it, but it sure makes things easier to read." > > <footer>- Hadley Wickham</footer> --- class: left ### Syntax style standards We can and should follow best practices for variable naming syntax despite R base code having inconsistencies. For R, this is covered very well in the [Advanced-R style guide](http://adv-r.had.co.nz/Style.html) and the [Tidyverse style guide](https://style.tidyverse.org/). The main points are: - Use **snake_case** for naming - Place spaces around all infix operators (**<-**, **+**, **-**, **/** , *****, **=**, **,**, **%in%**). This includes before indices in array indexing. Examples of this are: - `power_num <- function(a = 2, pow = 4)` - `y <- function(x, m, b){m * x + b}` - `dat[1, , 2]` - `arr_x[1, 1, ]` - `my_dataframe[, col_name_1]` - Indent two spaces inside functions, if conditionals, and for loops - use **<-** for assignment, not **=** - Place a space before left parenthesis unless it is a function call. --- class: left ### Syntax style standards - Poor vs properly formatted code .pull-left[.left[ **Poorly formatted** ```r batman <- function(line_thick = 1){ sc <- function(x) sqrt(1 - x ^ 2) el <- function(x) 3 * sc(abs(x) / 7) nl <- function(x) (-1) * el(x) sh <- function(x) 4.2 - 0.5 * abs(x) - 2.8 * sc(0.5 * abs(x) - 0.5) bf <- function(x) sc(abs(2 - abs(x)) - 1) - x ^ 2 / 11 + 0.5 * abs(x) - 3 cr <- data.frame(x = c(0, 0.5, 0.8, 1), y = c(1.7, 1.7, 2.6, 0.9)) cl <- data.frame(x = -cr$x, y = cr$y) plot_create<-function(fun, xmin, xmax){ list(left_plot=stat_function(fun=fun,xlim=c(xmin,xmax),size=line_thick),right_plot =stat_function(fun = fun,xlim=c(-xmax,-xmin),size=line_thick)) } g<-ggplot(data.frame(x=c(-7,7),y=c(-3, 3)),aes(x, y))+theme_bw()+theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(), axis.text = element_blank(),axis.ticks = element_blank()) + labs(x = "", y = "") upper_wing_plot<- plot_create(fun = el, xmin = 3, xmax = 7) lower_wing_plot <-plot_create(fun = nl, xmin = 4, xmax = 7) g <- g +upper_wing_plot$left_plot+upper_wing_plot$right_plot+lower_wing_plot$left_plot +lower_wing_plot$right_plot sh_plot <- plot_create(fun = sh, xmin = 1, xmax = 3) g <- g +sh_plot$left_plot + sh_plot$right_plot bt_plot <- plot_create(fun = bf, xmin = 0, xmax = 4) g=g+bt_plot$left_plot+bt_plot$right_plot +geom_path(data = cr, na.rm = TRUE, size = line_thick)+geom_path(data = cl, na.rm =T,size =line_thick) } batman(5) ``` ]] .pull-right[.left[ **Properly formatted** ```r batman <- function(line_thick = 1){ sc <- function(x) sqrt(1 - x ^ 2) el <- function(x) 3 * sc(abs(x) / 7) nl <- function(x) (-1) * el(x) sh <- function(x) 4.2 - 0.5 * abs(x) - 2.8 * sc(0.5 * abs(x) - 0.5) bf <- function(x) sc(abs(2 - abs(x)) - 1) - x ^ 2 / 11 + 0.5 * abs(x) - 3 cr <- data.frame(x = c(0, 0.5, 0.8, 1), y = c(1.7, 1.7, 2.6, 0.9)) cl <- data.frame(x = -cr$x, y = cr$y) plot_create <- function(fun, xmin, xmax){ list(left_plot = stat_function(fun = fun, xlim = c(xmin,xmax), size = line_thick), right_plot = stat_function(fun = fun, xlim = c(-xmax, -xmin), size = line_thick)) } g <- ggplot(data.frame(x = c(-7, 7), y = c(-3, 3)), aes(x, y)) + theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank()) + labs(x = "", y = "") upper_wing_plot <- plot_create(fun = el, xmin = 3, xmax = 7) lower_wing_plot <- plot_create(fun = nl, xmin = 4, xmax = 7) g <- g + upper_wing_plot$left_plot + upper_wing_plot$right_plot + lower_wing_plot$left_plot + lower_wing_plot$right_plot sh_plot <- plot_create(fun = sh, xmin = 1, xmax = 3) g <- g + sh_plot$left_plot + sh_plot$right_plot bt_plot <- plot_create(fun = bf, xmin = 0, xmax = 4) g + bt_plot$left_plot + bt_plot$right_plot + geom_path(data = cr, na.rm = TRUE, size = line_thick) + geom_path(data = cl, na.rm = TRUE, size = line_thick) } batman(5) ``` ]] --- class: left ### Syntax style standards - Properly formatted code run .pull-left[.left[ ```r batman <- function(line_thick = 1){ sc <- function(x) sqrt(1 - x ^ 2) el <- function(x) 3 * sc(abs(x) / 7) nl <- function(x) (-1) * el(x) sh <- function(x) 4.2 - 0.5 * abs(x) - 2.8 * sc(0.5 * abs(x) - 0.5) bf <- function(x) sc(abs(2 - abs(x)) - 1) - x ^ 2 / 11 + 0.5 * abs(x) - 3 cr <- data.frame(x = c(0, 0.5, 0.8, 1), y = c(1.7, 1.7, 2.6, 0.9)) cl <- data.frame(x = -cr$x, y = cr$y) plot_create <- function(fun, xmin, xmax){ list(left_plot = stat_function(fun = fun, xlim = c(xmin,xmax), size = line_thick), right_plot = stat_function(fun = fun, xlim = c(-xmax, -xmin), size = line_thick)) } g <- ggplot(data.frame(x = c(-7, 7), y = c(-3, 3)), aes(x, y)) + theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank()) + labs(x = "", y = "") upper_wing_plot <- plot_create(fun = el, xmin = 3, xmax = 7) lower_wing_plot <- plot_create(fun = nl, xmin = 4, xmax = 7) g <- g + upper_wing_plot$left_plot + upper_wing_plot$right_plot + lower_wing_plot$left_plot + lower_wing_plot$right_plot sh_plot <- plot_create(fun = sh, xmin = 1, xmax = 3) g <- g + sh_plot$left_plot + sh_plot$right_plot bt_plot <- plot_create(fun = bf, xmin = 0, xmax = 4) g + bt_plot$left_plot + bt_plot$right_plot + geom_path(data = cr, na.rm = TRUE, size = line_thick) + geom_path(data = cl, na.rm = TRUE, size = line_thick) } batman(5) ``` ]] .pull-right[.left[ <img src="knitr-figs/plot-batman-1.png" height="125" style="display: block; margin: auto;" /> <img src="img/batman-equation.png" width="602" height="200" style="display: block; margin: auto;" /> [Original source code and explanation](https://charlotte-ngs.github.io/BatmanPlot/BatmanPlotPost.html) ]] --- class: left ### Syntax style standards - dplyr, ggplot, and pipes Example of good code style using dplyr, ggplot (`+`), and pipes (`%>%` or `|>`): .pull-left[.left[ ```r language <- read.csv(here::here("data", "prog-lang-data.csv")) |> tibble::as_tibble() |> dplyr::pull(2) |> strsplit(";") |> unlist() %>% gsub(".*Shell.*", "Shell", .) tab <- table(language) |> tibble::as_tibble() ggplot(tab, aes(x = language, y = n)) + geom_bar(stat = "identity", color = "black", fill = "blue", alpha = 0.2) + theme(axis.text.x = element_text(angle = 45, hjust = 0.55, vjust = 0.5)) + scale_y_continuous(labels = scales::comma) + coord_cartesian(ylim = c(0, 60000), expand = FALSE) + xlab("Programming language") + ylab("Frequency") ``` ]] .pull-right[ <img src="knitr-figs/plot-good-code-style-pipes-1.png" style="display: block; margin: auto;" /> ] Always place new items piped with `%>%` or `|>`, or geoms added to ggplots with `+` on their own line: - Much easier to read - Allows them to be commented out easily - Less possibility of wrapping code past the end of the window frame Data source: [Kaggle](https://www.kaggle.com/datasets/deepakdhanoliya12/most-common-programming-languages-used-worldwide) --- class: left ### Syntax style standards - Function arguments - Example: `x` and `y` in this power function: `pow <- function(x, y){x ^ y}` - Often they look like the [scan()](https://github.com/SurajGupta/r-source/blob/master/src/library/base/R/scan.R) function in base R. .pull-left[.left[ **Hard to read** ```r scan <- function (file = "", what = double(), nmax = -1L, n = -1L, sep = "", quote = if (identical(sep, "\n")) "" else "'\"", dec = ".", skip = 0L, nlines = 0L, na.strings = "NA", flush = FALSE, fill = FALSE, strip.white = FALSE, quiet = FALSE, blank.lines.skip = TRUE, multi.line = TRUE, comment.char = "", allowEscapes = FALSE, fileEncoding = "", encoding = "unknown", text, skipNul = FALSE){ # Function body code here } ``` ]] .pull-right[.left[ **Easy to read** ```r scan <- function (file = "", what = double(), nmax = -1L, n = -1L, sep = "", quote = if (identical(sep, "\n")) "" else "'\"", dec = ".", skip = 0L, nlines = 0L, na.strings = "NA", flush = FALSE, fill = FALSE, strip.white = FALSE, quiet = FALSE, blank.lines.skip = TRUE, multi.line = TRUE, comment.char = "", allowEscapes = FALSE, fileEncoding = "", encoding = "unknown", text, skipNul = FALSE){ # Function body code here } ``` ]] --- class: center, middle, inverse # Variable Typing --- class: left ### Variable typing - Strong typing In most computer languages, variables are **strongly typed**. Here is an example in C++. - In this code, **all** variables are given a datatype that they must adhere to, including the return value from the function. - This produces fewer runtime bugs, because the compiler will tell you right away if you make a call to the function with the wrong type. .pull-left[.left[ ```cpp #include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] int fibonacci(int x) { bool base_num = x == 0 || x == 1; if(base_num) return(x); return(fibonacci(x - 1)) + fibonacci(x - 2); } ``` ```r fibonacci(12) #> [1] 144 ``` ]] --- class: left ### Variable typing - Weak typing In R, variables are **weakly typed**. In addition, R is **interpreted**, not **compiled** so you will not know there is a problem until your code runs to that point .pull-left[.left[ **Working code** ```r #' Multiply two numbers mult <- function(a, b){ r <- a * b r } mult(5, 3) #> [1] 15 ``` ]] .pull-right[.left[ **Error - wrong type in call** ```r d1 <- data.frame(j = c(1, 2, 3), k = c(4, 5, "a")) mult(5, d1) #> Error in FUN(left, right): non-numeric argument to binary operator ``` ]] - Weak typing leads to runtime errors. The only way in R to make sure the correct types are being passed as function arguments is to do **Argument verification** - **Argument verification** is essentially checking the types and dimensions of arguments at the beginning of a function. - Weak typing also allows functions which can return values depite being given different types as arguments. For example the `NROW()` and `NCOL()` functions (don't use them!!): .pull-left[.left[ ```r NROW(matrix(1:16, nrow = 4)) #> [1] 4 NROW(1:16) #> [1] 16 NCOL(1:16) #> [1] 1 ``` ]] --- class: left ### Argument validation - For strongly typed languages, this is done by the compiler implicitly and does not add overhead to the runtime performance. - For weakly typed languages, any code added in the function to check types is executed at runtime and will make your code slow. - There is a tradeoff here, fast code with no argument validation or slow code with complete validation. .pull-left[.left[ ```r get_model_info <- function(model_match, case_sens = TRUE){ if(!"character" %in% class(model_match)){ stop("`model_match` does not have class character", call. = FALSE) } if(length(model_match) > 1){ stop("length of `model_match` must be 1, you passed a length ", length(model_match), " vector", call. = FALSE) } if(!"logical" %in% class(case_sens)){ stop("`case_sens` does not have class logical", call. = FALSE) } if(length(case_sens) > 1){ stop("length of `case_sens` must be 1, you passed a length ", length(case_sens), " vector", call. = FALSE) } orig_car_dat <- mtcars |> as_tibble(rownames = "model") car_dat <- orig_car_dat if(!case_sens){ model_match <- tolower(model_match) car_dat$model <- tolower(car_dat$model) } grp <- grep(model_match, car_dat$model) if(!length(grp)){ stop("`model_match` does not match any model names in the ", "table", call. = FALSE) } orig_car_dat |> select(model, mpg, cyl, disp, hp, am, gear) |> slice(grp) } get_model_info(2) get_model_info(c("mazda", "toyota")) get_model_info("datsun", 1) get_model_info("mazda", case_sens = FALSE) ``` ]] .pull-right[.left[ ``` #> Error: `model_match` does not have class character #> Error: length of `model_match` must be 1, you passed a length 2 vector #> Error: `case_sens` does not have class logical #> # A tibble: 2 × 7 #> model mpg cyl disp hp am gear #> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 Mazda RX4 21 6 160 110 1 4 #> 2 Mazda RX4 Wag 21 6 160 110 1 4 ``` ]] --- class: left ### Argument validation - speed test .pull-left[.left[ ```r library(microbenchmark) calc <- function(a, b = 100, d = 10){ a * b ^ d } calc_loop <- function(iter = 1e4){ for(i in seq_len(iter)){ calc(a = i) } } microbenchmark( calc_loop() ) #> Unit: milliseconds #> expr min lq mean median uq max neval #> calc_loop() 5.9742 6.37215 7.979571 6.83035 8.4524 19.4623 100 ``` ]] .pull-left[.left[ ```r calc_with_checks <- function(a, b = 100, d = 10){ if(!"integer" %in% class(a)){ stop("`a` does not have class integer", call. = FALSE) } if(!"numeric" %in% class(b)){ stop("`b` does not have class numeric", call. = FALSE) } if(!"numeric" %in% class(d)){ stop("`d` does not have class numeric", call. = FALSE) } if(length(a) > 1){ stop("length of `a` must be 1, you passed a length ", length(a), " vector", call. = FALSE) } if(length(b) > 1){ stop("length of `b` must be 1, you passed a length ", length(b), " vector", call. = FALSE) } if(length(d) > 1){ stop("length of `d` must be 1, you passed a length ", length(d), " vector", call. = FALSE) } k <- a * b ^ d } calc_loop_checks <- function(iter = 1e4){ for(i in seq_len(iter)){ calc_with_checks(a = i) } } microbenchmark( calc_loop_checks() ) #> Unit: milliseconds #> expr min lq mean median uq max neval #> calc_loop_checks() 32.2994 37.8409 43.7701 43.3394 48.3691 67.0706 100 ``` ]] .pull-full[.left[ - The code with argument verification is about 5-6 times slower (median). - This is only 1 function in 1 loop with only 10,000 iterations. - Imagine many functions being called, each with argument verification, and millions of iterations. ]] --- class: center, middle, inverse # Global variables and Constants --- class: left ### Global variables - Avoid! - **Global variables** are variables which are visible to the whole project, declared outside functions. - Global variables are not a good idea in any language - Any function can read or write to them which means the global state of the program can change in many ways at any time - As the project complexity increases, keeping track of these changes becomes extremely difficult and frustrating - Eventually, debugging becomes impossible - Programming in this way is called **Monolithic** programming and was abandoned in the early 1980's. - Pass all variables as arguments to functions instead. --- class: left ### Global variables vs passing variables .pull-left[.left[ **With Global variable 'b'** ```r *b <- 2 pow <- function(a){ # Having 'b' here without it being an argument is bad! a ^ b } pow_vec <- function(vals){ out <- NULL for(i in seq_along(vals)){ out[i] <- pow(vals[i]) } out } pow_vec(vals = 1:10) #> [1] 1 4 9 16 25 36 49 64 81 100 ``` ]] .pull-left[.left[ **No Global variables** ```r pow <- function(a, b){ a ^ b } pow_vec <- function(vals, b){ out <- NULL for(i in seq_along(vals)){ out[i] <- pow(vals[i], b) } out } pow_vec(vals = 1:10, b = 2) #> [1] 1 4 9 16 25 36 49 64 81 100 ``` ]] --- class: left ### Constants In most languages, there is a CONST type which is like a variable but cannot be changed - In C++ and many other languages the declaration looks like this: ```cc const MY_CONSTANT = 42; ``` - Note the capital letters in upper snake case format. This is the way constant names appear in almost all languages - In R, there is no constant keyword. You must use a global variable and never change it. - Note that a global variable cannot be changed from within a function (unless you use `<<-`). - To lock the variable, imitating a constant, you can do this: ```r a <- 1 lockBinding("a", globalenv()) ``` - However, that will not prevent someone (or some function) from doing this: ```r rm(a) a <- 99 ``` --- class: center, middle, inverse # The Ellipsis parameter (...) --- class: left ### The Ellipsis parameter (...) - explained - The `...` parameter captures arguments passed into a function which has no associated named parameters. - The `...` parameter can be passed on from one function as an argument to another. - If a function does not have **ALL** arguments contained in the passed in `...` as parameters in its declaration, an error will be thrown. - To see the arguments passed in `...`, use `list(...)` within a function when `browser()` has stopped execution. .pull-left[.left[ **Error due to passing extra arguments into `func_1()`** ```r func_1 <- function(x, b){ message("In func_run(), b = ", b, ", x = ", x) } func_2 <- function(d){ message("In func_run(), d = ", d) } func_run <- function(a, b, ...){ message("In func_run(), a = ", a, ", b = ", b) func_1(b = b, ...) func_2(d = d, ...) } func_run(a = 1, b = 2, d = 3, x = 42, y = 43) #> In func_run(), a = 1, b = 2 #> Error in func_1(b = b, ...): unused arguments (d = 3, y = 43) ``` ]] .pull-right[.left[ **Add Ellipsis parameters to absorb extra arguments** ```r *func_1 <- function(x, b, ...){ message("In func_run(), b = ", b, ", x = ", x) } *func_2 <- function(d, ...){ message("In func_run(), d = ", d) } func_run <- function(a, b, ...){ message("In func_run(), a = ", a, ", b = ", b) func_1(b, ...) func_2(d, ...) } func_run(a = 1, b = 2, d = 3, x = 42, y = 43) #> In func_run(), a = 1, b = 2 #> In func_run(), b = 2, x = 42 #> In func_run(), d = 3 ``` ]] --- class: left ### *Promise already under evaluation* error Here is an example of some code which will cause a **promise already under evaluation** error: .pull-full[.left[ ```r j <- 42 foo <- function(j = j){ j } foo() #> Error in foo(): promise already under evaluation: recursive default argument reference or earlier problems? ``` ]] .pull-full[.left[ This is caused by parameters being set to defaults with the same name (e.g. `j = j`) in the function declaration and can be easily fixed by changing the parameter declaration to `k = j` or `j = k`. Use a different variable name in the function than the name of the variable containing the default value. ]] .pull-left[.left[ ```r j <- 42 foo <- function(k = j){ k } foo() #> [1] 42 ``` ]] .pull-full[.left[ This can be very difficult to fix properly if you pass these variables through several functions, because you don't want to come up with a new name for the parameter in each one. It can get really confusing really fast. The best way to solve this issue is to use the ellipsis parameter. ]] --- class: center ### How to fix promise errors with the ellipsis parameter .pull-left[.left[ ** Without the ellipsis parameter** ```r a <- 42 bar <- function(a = 21){ message("Inside bar(), a = ", a) a * a } *foo <- function(fun, x, a = a){ message("Inside foo(), x = ", x, ", a = ", a) * bar(a = a) } foo(x = 99, a = 10) #> Inside foo(), x = 99, a = 10 #> Inside bar(), a = 10 #> [1] 100 foo(x = 99, a = a) #> Inside foo(), x = 99, a = 42 #> Inside bar(), a = 42 #> [1] 1764 foo(x = 99) #> Error in lapply(list(...), as.character): promise already under evaluation: recursive default argument reference or earlier problems? ``` ]] .pull-right[.left[ ** With the ellipsis parameter** ```r a <- 42 bar <- function(a = 21){ message("Inside bar(), a = ", a) a * a } *foo <- function(x, ...){ message("Inside foo(), x = ", x, ", a = ", a) * bar(...) } foo(x = 99, a = 10) #> Inside foo(), x = 99, a = 42 #> Inside bar(), a = 10 #> [1] 100 foo(x = 99, a = a) #> Inside foo(), x = 99, a = 42 #> Inside bar(), a = 42 #> [1] 1764 foo(x = 99) #> Inside foo(), x = 99, a = 42 #> Inside bar(), a = 21 #> [1] 441 ``` ]] --- class: center, middle, inverse # Tibbles --- class: left ### Tibbles - explained - **tibbles** are just **data.frames** with some special output properties so that viewing them in the console is much nicer. To convert a data frame to a tibble, use `tibble::as_tibble()`. - **tibbles** only show the first ten rows so the column headers don't run off the top of the screen, and each column type is shown at the top. Negative numbers are colored red (in RStudio). - **tibbles** do not change any data type from its original source. `data.frame()` does this with its argument `stringsAsFactors`. - **.red[BEWARE]** If you use data frames (not tibbles), the function `data.frame()` changed its argument `stringsAsFactors` to `FALSE` as of R 4.0.0 -- .pull-left[.left[ **Without row names** ```r *iris_tibble <- iris |> tibble::as_tibble() knitr::kable(iris_tibble, format = "html") |> kableExtra::kable_styling(font_size = 12) ``` <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:right;"> Sepal.Length </th> <th style="text-align:right;"> Sepal.Width </th> <th style="text-align:right;"> Petal.Length </th> <th style="text-align:right;"> Petal.Width </th> <th style="text-align:left;"> Species </th> </tr> </thead> <tbody> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.7 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.6 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.6 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 3.9 </td> <td style="text-align:right;"> 1.7 </td> <td style="text-align:right;"> 0.4 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.6 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.3 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.1 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 3.7 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.1 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.3 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 1.1 </td> <td style="text-align:right;"> 0.1 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 4.0 </td> <td style="text-align:right;"> 1.2 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.4 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 3.9 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:right;"> 0.4 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.3 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 3.8 </td> <td style="text-align:right;"> 1.7 </td> <td style="text-align:right;"> 0.3 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.8 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.3 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.7 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.7 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.4 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.6 </td> <td style="text-align:right;"> 3.6 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 1.7 </td> <td style="text-align:right;"> 0.5 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.9 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:right;"> 0.4 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.2 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.2 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.7 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.4 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.2 </td> <td style="text-align:right;"> 4.1 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.1 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 4.2 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 1.2 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 3.6 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.1 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:right;"> 0.3 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:right;"> 0.3 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:right;"> 0.6 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.8 </td> <td style="text-align:right;"> 1.9 </td> <td style="text-align:right;"> 0.4 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.3 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 3.8 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 4.6 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.3 </td> <td style="text-align:right;"> 3.7 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:right;"> 0.2 </td> <td style="text-align:left;"> setosa </td> </tr> <tr> <td style="text-align:right;"> 7.0 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 4.7 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.9 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:right;"> 4.0 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.5 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.6 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 4.7 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 2.4 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.6 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 4.6 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.2 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 3.9 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 2.0 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.9 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.2 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 2.2 </td> <td style="text-align:right;"> 4.0 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 4.7 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 3.6 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 4.1 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.2 </td> <td style="text-align:right;"> 2.2 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 3.9 </td> <td style="text-align:right;"> 1.1 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.9 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.0 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.7 </td> <td style="text-align:right;"> 1.2 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 4.3 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.6 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.8 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 1.7 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.6 </td> <td style="text-align:right;"> 3.5 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 2.4 </td> <td style="text-align:right;"> 3.8 </td> <td style="text-align:right;"> 1.1 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 2.4 </td> <td style="text-align:right;"> 3.7 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 3.9 </td> <td style="text-align:right;"> 1.2 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 4.7 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.1 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 4.0 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 2.6 </td> <td style="text-align:right;"> 4.4 </td> <td style="text-align:right;"> 1.2 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.6 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 2.6 </td> <td style="text-align:right;"> 4.0 </td> <td style="text-align:right;"> 1.2 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 1.0 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 4.2 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.2 </td> <td style="text-align:right;"> 1.2 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 4.2 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.2 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 4.3 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 1.1 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.1 </td> <td style="text-align:right;"> 1.3 </td> <td style="text-align:left;"> versicolor </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 1.9 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.1 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.9 </td> <td style="text-align:right;"> 2.1 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.5 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 2.2 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.6 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 6.6 </td> <td style="text-align:right;"> 2.1 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 4.5 </td> <td style="text-align:right;"> 1.7 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.3 </td> <td style="text-align:right;"> 2.9 </td> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.2 </td> <td style="text-align:right;"> 3.6 </td> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.5 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 2.0 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 5.3 </td> <td style="text-align:right;"> 1.9 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.8 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 2.1 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 2.0 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 2.4 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 5.3 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.5 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.7 </td> <td style="text-align:right;"> 3.8 </td> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 2.2 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.7 </td> <td style="text-align:right;"> 2.6 </td> <td style="text-align:right;"> 6.9 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 2.2 </td> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.9 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 2.0 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.7 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 2.0 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.1 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.2 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.2 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.9 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.1 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.2 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 1.6 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.4 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 1.9 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.9 </td> <td style="text-align:right;"> 3.8 </td> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 2.0 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.2 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 2.8 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 1.5 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 2.6 </td> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 1.4 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 7.7 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 6.1 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.4 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.4 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 5.5 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.0 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 4.8 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.9 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 2.1 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 5.6 </td> <td style="text-align:right;"> 2.4 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.9 </td> <td style="text-align:right;"> 3.1 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 5.8 </td> <td style="text-align:right;"> 2.7 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 1.9 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.8 </td> <td style="text-align:right;"> 3.2 </td> <td style="text-align:right;"> 5.9 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 3.3 </td> <td style="text-align:right;"> 5.7 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.7 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.2 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.3 </td> <td style="text-align:right;"> 2.5 </td> <td style="text-align:right;"> 5.0 </td> <td style="text-align:right;"> 1.9 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.5 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.2 </td> <td style="text-align:right;"> 2.0 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 6.2 </td> <td style="text-align:right;"> 3.4 </td> <td style="text-align:right;"> 5.4 </td> <td style="text-align:right;"> 2.3 </td> <td style="text-align:left;"> virginica </td> </tr> <tr> <td style="text-align:right;"> 5.9 </td> <td style="text-align:right;"> 3.0 </td> <td style="text-align:right;"> 5.1 </td> <td style="text-align:right;"> 1.8 </td> <td style="text-align:left;"> virginica </td> </tr> </tbody> </table> ]] .pull-right[.left[ **Convert row names into column** ```r *mtcars_tibble <- mtcars |> tibble::as_tibble(rownames = "model") knitr::kable(mtcars_tibble, format = "html") |> kableExtra::kable_styling(font_size = 12) ``` <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> model </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> drat </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> qsec </th> <th style="text-align:right;"> vs </th> <th style="text-align:right;"> am </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 160.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 16.46 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 160.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.90 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 108.0 </td> <td style="text-align:right;"> 93 </td> <td style="text-align:right;"> 3.85 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 18.61 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 258.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.08 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 19.44 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;"> 18.7 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 360.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.15 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 17.02 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;"> 18.1 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 225.0 </td> <td style="text-align:right;"> 105 </td> <td style="text-align:right;"> 2.76 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 20.22 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Duster 360 </td> <td style="text-align:right;"> 14.3 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 360.0 </td> <td style="text-align:right;"> 245 </td> <td style="text-align:right;"> 3.21 </td> <td style="text-align:right;"> 3.570 </td> <td style="text-align:right;"> 15.84 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Merc 240D </td> <td style="text-align:right;"> 24.4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 146.7 </td> <td style="text-align:right;"> 62 </td> <td style="text-align:right;"> 3.69 </td> <td style="text-align:right;"> 3.190 </td> <td style="text-align:right;"> 20.00 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Merc 230 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 140.8 </td> <td style="text-align:right;"> 95 </td> <td style="text-align:right;"> 3.92 </td> <td style="text-align:right;"> 3.150 </td> <td style="text-align:right;"> 22.90 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Merc 280 </td> <td style="text-align:right;"> 19.2 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 167.6 </td> <td style="text-align:right;"> 123 </td> <td style="text-align:right;"> 3.92 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 18.30 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Merc 280C </td> <td style="text-align:right;"> 17.8 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 167.6 </td> <td style="text-align:right;"> 123 </td> <td style="text-align:right;"> 3.92 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 18.90 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SE </td> <td style="text-align:right;"> 16.4 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 3.07 </td> <td style="text-align:right;"> 4.070 </td> <td style="text-align:right;"> 17.40 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SL </td> <td style="text-align:right;"> 17.3 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 3.07 </td> <td style="text-align:right;"> 3.730 </td> <td style="text-align:right;"> 17.60 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SLC </td> <td style="text-align:right;"> 15.2 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 3.07 </td> <td style="text-align:right;"> 3.780 </td> <td style="text-align:right;"> 18.00 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Cadillac Fleetwood </td> <td style="text-align:right;"> 10.4 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 472.0 </td> <td style="text-align:right;"> 205 </td> <td style="text-align:right;"> 2.93 </td> <td style="text-align:right;"> 5.250 </td> <td style="text-align:right;"> 17.98 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Lincoln Continental </td> <td style="text-align:right;"> 10.4 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 460.0 </td> <td style="text-align:right;"> 215 </td> <td style="text-align:right;"> 3.00 </td> <td style="text-align:right;"> 5.424 </td> <td style="text-align:right;"> 17.82 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Chrysler Imperial </td> <td style="text-align:right;"> 14.7 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 440.0 </td> <td style="text-align:right;"> 230 </td> <td style="text-align:right;"> 3.23 </td> <td style="text-align:right;"> 5.345 </td> <td style="text-align:right;"> 17.42 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Fiat 128 </td> <td style="text-align:right;"> 32.4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 78.7 </td> <td style="text-align:right;"> 66 </td> <td style="text-align:right;"> 4.08 </td> <td style="text-align:right;"> 2.200 </td> <td style="text-align:right;"> 19.47 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Honda Civic </td> <td style="text-align:right;"> 30.4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 75.7 </td> <td style="text-align:right;"> 52 </td> <td style="text-align:right;"> 4.93 </td> <td style="text-align:right;"> 1.615 </td> <td style="text-align:right;"> 18.52 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Toyota Corolla </td> <td style="text-align:right;"> 33.9 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 71.1 </td> <td style="text-align:right;"> 65 </td> <td style="text-align:right;"> 4.22 </td> <td style="text-align:right;"> 1.835 </td> <td style="text-align:right;"> 19.90 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Toyota Corona </td> <td style="text-align:right;"> 21.5 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 120.1 </td> <td style="text-align:right;"> 97 </td> <td style="text-align:right;"> 3.70 </td> <td style="text-align:right;"> 2.465 </td> <td style="text-align:right;"> 20.01 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Dodge Challenger </td> <td style="text-align:right;"> 15.5 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 318.0 </td> <td style="text-align:right;"> 150 </td> <td style="text-align:right;"> 2.76 </td> <td style="text-align:right;"> 3.520 </td> <td style="text-align:right;"> 16.87 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> AMC Javelin </td> <td style="text-align:right;"> 15.2 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 304.0 </td> <td style="text-align:right;"> 150 </td> <td style="text-align:right;"> 3.15 </td> <td style="text-align:right;"> 3.435 </td> <td style="text-align:right;"> 17.30 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Camaro Z28 </td> <td style="text-align:right;"> 13.3 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 350.0 </td> <td style="text-align:right;"> 245 </td> <td style="text-align:right;"> 3.73 </td> <td style="text-align:right;"> 3.840 </td> <td style="text-align:right;"> 15.41 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Pontiac Firebird </td> <td style="text-align:right;"> 19.2 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 400.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.08 </td> <td style="text-align:right;"> 3.845 </td> <td style="text-align:right;"> 17.05 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Fiat X1-9 </td> <td style="text-align:right;"> 27.3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 79.0 </td> <td style="text-align:right;"> 66 </td> <td style="text-align:right;"> 4.08 </td> <td style="text-align:right;"> 1.935 </td> <td style="text-align:right;"> 18.90 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Porsche 914-2 </td> <td style="text-align:right;"> 26.0 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 120.3 </td> <td style="text-align:right;"> 91 </td> <td style="text-align:right;"> 4.43 </td> <td style="text-align:right;"> 2.140 </td> <td style="text-align:right;"> 16.70 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Lotus Europa </td> <td style="text-align:right;"> 30.4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 95.1 </td> <td style="text-align:right;"> 113 </td> <td style="text-align:right;"> 3.77 </td> <td style="text-align:right;"> 1.513 </td> <td style="text-align:right;"> 16.90 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Ford Pantera L </td> <td style="text-align:right;"> 15.8 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 351.0 </td> <td style="text-align:right;"> 264 </td> <td style="text-align:right;"> 4.22 </td> <td style="text-align:right;"> 3.170 </td> <td style="text-align:right;"> 14.50 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Ferrari Dino </td> <td style="text-align:right;"> 19.7 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;"> 145.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.62 </td> <td style="text-align:right;"> 2.770 </td> <td style="text-align:right;"> 15.50 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Maserati Bora </td> <td style="text-align:right;"> 15.0 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;"> 301.0 </td> <td style="text-align:right;"> 335 </td> <td style="text-align:right;"> 3.54 </td> <td style="text-align:right;"> 3.570 </td> <td style="text-align:right;"> 14.60 </td> <td style="text-align:right;"> 0 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Volvo 142E </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 121.0 </td> <td style="text-align:right;"> 109 </td> <td style="text-align:right;"> 4.11 </td> <td style="text-align:right;"> 2.780 </td> <td style="text-align:right;"> 18.60 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> </tr> </tbody> </table> ]] --- class: left ### Tibbles - creation Making a tibble from scratch is the same as making a `data.frame`. This code makes a tibble of numbers which follow **Benford's law** and plots them using `ggplot`: .pull-left[.left[ ```r num_draws <- 100000 *df <- tibble::tibble(num = 10 ^ runif(num_draws)) |> mutate(num_char = as.character(num)) |> mutate(num_char = stringr::str_sub(num_char, 1, 1)) |> select(-num) |> table() df <- df / sum(df) df <- df |> * tibble::as_tibble() ggplot(df, aes(x = num_char, y = n)) + geom_bar(stat="identity", fill = "#0000FF4D", color = "black") + scale_y_continuous(labels = scales::comma) + ylab("Probability") + xlab("First digit in number") ``` ]] .pull-right[.left[ <img src="knitr-figs/make-tibble-fig-1.png" height="350" style="display: block; margin: auto;" /> ]] --- class: center, middle, inverse # All loops are `for()` loops --- class: left ### `for()`, `lapply()`, and `purrr::map()` Using `for()` loops come naturally to people familiar with procedural programming, and is more intuitive so newcomers to R tend to use them a lot. .pull-left[.left[ A `for()` loop ```r # Cube a vector of numbers output <- NULL for(x in 1:10){ output[x] <- x ^ 3 } print(output) #> [1] 1 8 27 64 125 216 343 512 729 1000 ``` ]] .pull-right[.left[ The same loop using base R's `lapply` method: ```r lapply(1:10, function(x){ x ^ 3 }) |> unlist() #> [1] 1 8 27 64 125 216 343 512 729 1000 ``` ]] .pull-left[.left[ The same loop using the `purrr::map_dbl()` method: ```r *purrr::map(1:10, function(x){ x ^ 3 }) |> unlist() #> [1] 1 8 27 64 125 216 343 512 729 1000 ``` ]] .pull-right[.left[ Using the `purrr::map_dbl()` method with the function shortcut (`~`): ```r *purrr::map(1:10, ~{ .x ^ 3 }) |> unlist() #> [1] 1 8 27 64 125 216 343 512 729 1000 ``` ]] .pull-full[.left[ The `purrr::map()` method allows use of `~` as a shorthand form for `function(x)` and each list element is assigned to `.x`. ]] --- class: left ### `apply` methods are not guaranteed to return the correct type - Here is an example using `sapply()` and `vapply()` compared to `map_lgl()`: .pull-left[.left[ The `sapply()` and `vapply()` functions return different types based on the input ```r sapply(LETTERS[1:3], function(x) {x == "B"}) #> A B C #> FALSE TRUE FALSE sapply(LETTERS[0], function(x) {x == "B"}) #> named list() vapply(LETTERS[1:3], function(x) {x == "B"}, logical(1)) #> A B C #> FALSE TRUE FALSE vapply(LETTERS[0], function(x) {x == "B"}, logical(1)) #> named logical(0) ``` ]] .pull-left[.left[ The `map()` commands always return the correct type ```r purrr::map_lgl(LETTERS[1:3], function(x) {x == "B"}) #> [1] FALSE TRUE FALSE purrr::map_lgl(LETTERS[0], function(x) {x == "B"}) #> logical(0) ``` ]] --- class: left ### Using `purrr::imap()` and `purrr::map2()` One thing that come up quite often is that you have a list of data frames that need the list element number or list names appended to the individual data frames. `imap()` supplies the names of the list elements. If there are no names, it supplies the element numbers. `map2()` can be guaranteed to supply the list element numbers. One reason this happens is if you have N simulations and you want to append the simulation number to each data frame, and then merge those data frames into one large one so that the data are in the correct format for `ggplot` plots. .pull-left[.left[ **Using `imap()`** ```r # Split the mtcars data frame by column `cyl` into a list of data frames lst <- mtcars |> tibble::as_tibble(rownames = "model") |> select(-c(vs, qsec, am, drat)) |> split(~cyl) *df_imap <- purrr::imap(lst, ~{ .x |> dplyr::mutate(grp = .y) # Add the group name }) |> purrr::map_df(~{.x}) # Bind all rows ``` ]] .pull-right[.left[ **Using `map2()`** ```r # Split the mtcars data frame by column `cyl` into a list of data frames lst <- mtcars |> tibble::as_tibble(rownames = "model") |> select(-c(vs, qsec, am, drat)) |> split(~cyl) *df_map2 <- purrr::map2(lst, seq_along(lst), ~{ .x |> dplyr::mutate(grp = .y) # Add the group number }) |> purrr::map_df(~{.x}) # Bind all rows ``` ]] --- class: left ### Using `purrr::imap()` and `purrr::map2()` - output .pull-left[.left[ **Using `imap(lst)`** <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> model </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> <th style="text-align:left;"> grp </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 108.0 </td> <td style="text-align:right;"> 93 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Merc 240D </td> <td style="text-align:right;"> 24.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 146.7 </td> <td style="text-align:right;"> 62 </td> <td style="text-align:right;"> 3.190 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Merc 230 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 140.8 </td> <td style="text-align:right;"> 95 </td> <td style="text-align:right;"> 3.150 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Fiat 128 </td> <td style="text-align:right;"> 32.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 78.7 </td> <td style="text-align:right;"> 66 </td> <td style="text-align:right;"> 2.200 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Honda Civic </td> <td style="text-align:right;"> 30.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 75.7 </td> <td style="text-align:right;"> 52 </td> <td style="text-align:right;"> 1.615 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Toyota Corolla </td> <td style="text-align:right;"> 33.9 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 71.1 </td> <td style="text-align:right;"> 65 </td> <td style="text-align:right;"> 1.835 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Toyota Corona </td> <td style="text-align:right;"> 21.5 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 120.1 </td> <td style="text-align:right;"> 97 </td> <td style="text-align:right;"> 2.465 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Fiat X1-9 </td> <td style="text-align:right;"> 27.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 79.0 </td> <td style="text-align:right;"> 66 </td> <td style="text-align:right;"> 1.935 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Porsche 914-2 </td> <td style="text-align:right;"> 26.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 120.3 </td> <td style="text-align:right;"> 91 </td> <td style="text-align:right;"> 2.140 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Lotus Europa </td> <td style="text-align:right;"> 30.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 95.1 </td> <td style="text-align:right;"> 113 </td> <td style="text-align:right;"> 1.513 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Volvo 142E </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 121.0 </td> <td style="text-align:right;"> 109 </td> <td style="text-align:right;"> 2.780 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 160.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 160.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 258.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;"> 18.1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 225.0 </td> <td style="text-align:right;"> 105 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Merc 280 </td> <td style="text-align:right;"> 19.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 167.6 </td> <td style="text-align:right;"> 123 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Merc 280C </td> <td style="text-align:right;"> 17.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 167.6 </td> <td style="text-align:right;"> 123 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Ferrari Dino </td> <td style="text-align:right;"> 19.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 145.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 2.770 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;"> 18.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 360.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Duster 360 </td> <td style="text-align:right;"> 14.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 360.0 </td> <td style="text-align:right;"> 245 </td> <td style="text-align:right;"> 3.570 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SE </td> <td style="text-align:right;"> 16.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 4.070 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SL </td> <td style="text-align:right;"> 17.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 3.730 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SLC </td> <td style="text-align:right;"> 15.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 3.780 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Cadillac Fleetwood </td> <td style="text-align:right;"> 10.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 472.0 </td> <td style="text-align:right;"> 205 </td> <td style="text-align:right;"> 5.250 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Lincoln Continental </td> <td style="text-align:right;"> 10.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 460.0 </td> <td style="text-align:right;"> 215 </td> <td style="text-align:right;"> 5.424 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Chrysler Imperial </td> <td style="text-align:right;"> 14.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 440.0 </td> <td style="text-align:right;"> 230 </td> <td style="text-align:right;"> 5.345 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Dodge Challenger </td> <td style="text-align:right;"> 15.5 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 318.0 </td> <td style="text-align:right;"> 150 </td> <td style="text-align:right;"> 3.520 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> AMC Javelin </td> <td style="text-align:right;"> 15.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 304.0 </td> <td style="text-align:right;"> 150 </td> <td style="text-align:right;"> 3.435 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Camaro Z28 </td> <td style="text-align:right;"> 13.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 350.0 </td> <td style="text-align:right;"> 245 </td> <td style="text-align:right;"> 3.840 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Pontiac Firebird </td> <td style="text-align:right;"> 19.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 400.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.845 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Ford Pantera L </td> <td style="text-align:right;"> 15.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 351.0 </td> <td style="text-align:right;"> 264 </td> <td style="text-align:right;"> 3.170 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> <tr> <td style="text-align:left;"> Maserati Bora </td> <td style="text-align:right;"> 15.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 301.0 </td> <td style="text-align:right;"> 335 </td> <td style="text-align:right;"> 3.570 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:left;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> </tr> </tbody> </table> ]] .pull-right[.left[ **Using `map2(lst, seq_along(lst))`** <table class="table" style="font-size: 12px; margin-left: auto; margin-right: auto;"> <thead> <tr> <th style="text-align:left;"> model </th> <th style="text-align:right;"> mpg </th> <th style="text-align:right;"> cyl </th> <th style="text-align:right;"> disp </th> <th style="text-align:right;"> hp </th> <th style="text-align:right;"> wt </th> <th style="text-align:right;"> gear </th> <th style="text-align:right;"> carb </th> <th style="text-align:right;"> grp </th> </tr> </thead> <tbody> <tr> <td style="text-align:left;"> Datsun 710 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 108.0 </td> <td style="text-align:right;"> 93 </td> <td style="text-align:right;"> 2.320 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Merc 240D </td> <td style="text-align:right;"> 24.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 146.7 </td> <td style="text-align:right;"> 62 </td> <td style="text-align:right;"> 3.190 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Merc 230 </td> <td style="text-align:right;"> 22.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 140.8 </td> <td style="text-align:right;"> 95 </td> <td style="text-align:right;"> 3.150 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Fiat 128 </td> <td style="text-align:right;"> 32.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 78.7 </td> <td style="text-align:right;"> 66 </td> <td style="text-align:right;"> 2.200 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Honda Civic </td> <td style="text-align:right;"> 30.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 75.7 </td> <td style="text-align:right;"> 52 </td> <td style="text-align:right;"> 1.615 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Toyota Corolla </td> <td style="text-align:right;"> 33.9 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 71.1 </td> <td style="text-align:right;"> 65 </td> <td style="text-align:right;"> 1.835 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Toyota Corona </td> <td style="text-align:right;"> 21.5 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 120.1 </td> <td style="text-align:right;"> 97 </td> <td style="text-align:right;"> 2.465 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Fiat X1-9 </td> <td style="text-align:right;"> 27.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 79.0 </td> <td style="text-align:right;"> 66 </td> <td style="text-align:right;"> 1.935 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Porsche 914-2 </td> <td style="text-align:right;"> 26.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 120.3 </td> <td style="text-align:right;"> 91 </td> <td style="text-align:right;"> 2.140 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Lotus Europa </td> <td style="text-align:right;"> 30.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 95.1 </td> <td style="text-align:right;"> 113 </td> <td style="text-align:right;"> 1.513 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Volvo 142E </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 4 </td> <td style="text-align:right;"> 121.0 </td> <td style="text-align:right;"> 109 </td> <td style="text-align:right;"> 2.780 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 1 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 160.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 2.620 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Mazda RX4 Wag </td> <td style="text-align:right;"> 21.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 160.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 2.875 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Hornet 4 Drive </td> <td style="text-align:right;"> 21.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 258.0 </td> <td style="text-align:right;"> 110 </td> <td style="text-align:right;"> 3.215 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Valiant </td> <td style="text-align:right;"> 18.1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 225.0 </td> <td style="text-align:right;"> 105 </td> <td style="text-align:right;"> 3.460 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 1 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Merc 280 </td> <td style="text-align:right;"> 19.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 167.6 </td> <td style="text-align:right;"> 123 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Merc 280C </td> <td style="text-align:right;"> 17.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 167.6 </td> <td style="text-align:right;"> 123 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Ferrari Dino </td> <td style="text-align:right;"> 19.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 6 </td> <td style="text-align:right;"> 145.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 2.770 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 6 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 2 </td> </tr> <tr> <td style="text-align:left;"> Hornet Sportabout </td> <td style="text-align:right;"> 18.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 360.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.440 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Duster 360 </td> <td style="text-align:right;"> 14.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 360.0 </td> <td style="text-align:right;"> 245 </td> <td style="text-align:right;"> 3.570 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SE </td> <td style="text-align:right;"> 16.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 4.070 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SL </td> <td style="text-align:right;"> 17.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 3.730 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Merc 450SLC </td> <td style="text-align:right;"> 15.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 275.8 </td> <td style="text-align:right;"> 180 </td> <td style="text-align:right;"> 3.780 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Cadillac Fleetwood </td> <td style="text-align:right;"> 10.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 472.0 </td> <td style="text-align:right;"> 205 </td> <td style="text-align:right;"> 5.250 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Lincoln Continental </td> <td style="text-align:right;"> 10.4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 460.0 </td> <td style="text-align:right;"> 215 </td> <td style="text-align:right;"> 5.424 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Chrysler Imperial </td> <td style="text-align:right;"> 14.7 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 440.0 </td> <td style="text-align:right;"> 230 </td> <td style="text-align:right;"> 5.345 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Dodge Challenger </td> <td style="text-align:right;"> 15.5 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 318.0 </td> <td style="text-align:right;"> 150 </td> <td style="text-align:right;"> 3.520 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> AMC Javelin </td> <td style="text-align:right;"> 15.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 304.0 </td> <td style="text-align:right;"> 150 </td> <td style="text-align:right;"> 3.435 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Camaro Z28 </td> <td style="text-align:right;"> 13.3 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 350.0 </td> <td style="text-align:right;"> 245 </td> <td style="text-align:right;"> 3.840 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Pontiac Firebird </td> <td style="text-align:right;"> 19.2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 400.0 </td> <td style="text-align:right;"> 175 </td> <td style="text-align:right;"> 3.845 </td> <td style="text-align:right;"> 3 </td> <td style="text-align:right;"> 2 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Ford Pantera L </td> <td style="text-align:right;"> 15.8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 351.0 </td> <td style="text-align:right;"> 264 </td> <td style="text-align:right;"> 3.170 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 4 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> <tr> <td style="text-align:left;"> Maserati Bora </td> <td style="text-align:right;"> 15.0 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 8 </td> <td style="text-align:right;"> 301.0 </td> <td style="text-align:right;"> 335 </td> <td style="text-align:right;"> 3.570 </td> <td style="text-align:right;"> 5 </td> <td style="text-align:right;"> 8 </td> <td style="text-align:right;font-weight: bold;color: black !important;background-color: yellow !important;"> 3 </td> </tr> </tbody> </table> ]] --- class: left ### Using `map()` with ellipsis passed to internal functions This is a common thing you need to do if you're using the `map()` functions but strangely there are no examples that I could find online for this. Using this method you can pass N arguments into the function which is applied to each element of the list. .pull-full[.left[ ```r ultimate_power <- function(val, pow){ val ^ pow } power_vec <- function(lst, ...){ purrr::map_dbl(lst, function(list_item = .x, ...){ ultimate_power(list_item, ...) }, ...) } power_vec(1:10, 3) #> [1] 1 8 27 64 125 216 343 512 729 1000 power_vec(11:20, 4) #> [1] 14641 20736 28561 38416 50625 65536 83521 104976 130321 160000 power_vec(21:30, 5) #> [1] 4084101 5153632 6436343 7962624 9765625 11881376 14348907 17210368 20511149 24300000 ``` ]] --- class: center # Thank you! Click the GitHub cat for the source code used to build these slides <a href="https://github.com/cgrandin/good-code-practices" class="github-corner" aria-label="View source on Github"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#fff; color:#151513; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style> <a href="https://yihui.org/knitr/" target="_blank"><img src="img/knitr.png" width="125" style="display: block; margin: auto;" /></a> <a href="https://rmarkdown.rstudio.com/" target="_blank"><img src="img/rmarkdown.png" width="125" style="display: block; margin: auto;" /></a> <a href="https://bookdown.org/yihui/rmarkdown/xaringan.html" target="_blank"><img src="img/xaringan.png" width="125" style="display: block; margin: auto;" /></a>