---
title: A field guide to base R
author: Aryan Kancherla and David Kane
tutorial:
  id: a-field-guide-to-base-R
output:
  learnr::tutorial:
    progressive: yes
    allow_skip: yes
runtime: shiny_prerendered
description: 'Tutorial for Chapter 27: A field guide to base R'
---

```{r setup, include = FALSE}
library(learnr)
library(tutorial.helpers)
library(tidyverse)

knitr::opts_chunk$set(echo = FALSE)
options(tutorial.exercise.timelimit = 60, 
        tutorial.storage = "local") 


x <- c("one", "two", "three", "four", "five")

x2 <- c(10, 3, NA, 5, 8, 1, NA)

x3 <- c(abc = 1, def = 2, xyz = 5)

df <- tibble(
  x = 1:3, 
  y = c("a", "e", "f"), 
  z = runif(3)
)

df0 <- tibble(
  x = c(2, 3, 1, 1, NA), 
  y = letters[1:5], 
  z = runif(5)
) 

df2 <- data.frame(x1 = 1)

tb <- tibble(
  x = 1:4,
  y = c(10, 4, 1, 21)
)

tb2 <- tibble(x1 = 1)

list1 <- list(
  a = 1:3, 
  b = "a string", 
  c = pi, 
  d = list(-1, -5)
)

L <- list(15, 16, 17, 18, 19)

L2 <- list(4, 16, 25, 49, 64)

df4 <- tibble(a = 1, b = 2, c = "a", d = "b", e = 4)

tb4 <- tibble(
  col1 = list(1, 2, 3, 4),
  col2 = list(11, 12, 13, 14)
)

num_cols <- sapply(df4, is.numeric)


save_data <- vector(mode = "list" , length = length(tb4))
indexes <- seq_along(tb4)



```

```{r copy-code-chunk, child = system.file("child_documents/copy_button.Rmd", package = "tutorial.helpers")}
```

```{r info-section, child = system.file("child_documents/info_section.Rmd", package = "tutorial.helpers")}
```


## Introduction
### 

*This is a ROUGH, UNFINISHED, draft.*

This tutorial covers [Chapter 27: A field guide to base R](https://r4ds.hadley.nz/base-r) from [*R for Data Science (2e)*](https://r4ds.hadley.nz/) by Hadley Wickham, Mine Çetinkaya-Rundel, and Garrett Grolemund.

In this chapter, we'll focus on four big topics: subsetting with `[`, subsetting with `[[` and `$`, the *apply* family of functions, and `for` loops. To finish off, we'll briefly discuss two essential plotting functions. 

## Subsetting with the single bracket operator
### 

The `[` bracket can be used to extract sub-components from data frames and vectors, with the syntax `x[i]`. `x` represents the vector and `i` represents the position of the value inside of `x` (1st element is position 1, second element is position 2, and so forth).

### Exercise 1

Load the tidyverse library

```{r subsetting-with-the--1, exercise = TRUE}

```

```{r subsetting-with-the--1-hint-1, eval = FALSE}
library(...)
```

```{r, include = FALSE}
library(tidyverse)
```

### 

There are five main types of things that you can subset a vector with, which will be covered in the following exercises:

1)  A vector of positive integers
2)  A vector of negative integers
3)  A logical vector
4)  A character vector
5)  Nothing

### Exercise 2

Press "Run Code".

```{r subsetting-with-the--2, exercise = TRUE}
x <- c("one", "two", "three", "four", "five")
```

```{r, include = FALSE}
x <- c("one", "two", "three", "four", "five")
```

### 

This code sets the variable `x` to the vector `c("one", "two", "three", "four", "five")`.

### Exercise 3

Extract the first element of `x` by typing `x[]` with the number `1` inside the brackets

```{r subsetting-with-the--3, exercise = TRUE}

```

```{r subsetting-with-the--3-hint-1, eval = FALSE}
x[...]
```

```{r, include = FALSE}
x[1]
```

### 

As you can see, the code extracts the first value of the `x` vector, printing out the value "one".

### Exercise 4

We can also pass in a vector to `[]`, containing various positions to extract from `x`. In the code chunk below, extract the 2nd, 3rd, and 4th values of `x`, using `c()`

```{r subsetting-with-the--4, exercise = TRUE}

```

```{r subsetting-with-the--4-hint-1, eval = FALSE}
x[c(..., ..., ...)]
```

```{r, include = FALSE}
x[c(2, 3, 4)]
```

### 

When you run the code above, you should see that it extracts "two", "three", and "four". By using vectors inside `[]`, you can extract multiple elements at once.

### Exercise 5

You can also pass in a vector of negative values. In the code chunk below, type `x[]`, placing the vector `c(-1, -2)` inside the brackets. Oberseve what happens.

```{r subsetting-with-the--5, exercise = TRUE}

```

```{r subsetting-with-the--5-hint-1, eval = FALSE}
x[c(..., ...)]
```

```{r, include = FALSE}
x[c(-1, -2)]
```

### 

Negative values drop the elements at the specified positions; the code above drops the first and second elements, returning "three", "four", and "five".

### Exercise 6

Subsetting with logical vectors are another type of thing that you can subset a vector with. Create a vector with the values `10`, `3`, `NA`, `5`, `8`, `1`, and `NA`. Save this to a variable named `x2`.

```{r subsetting-with-the--6, exercise = TRUE}

```

```{r subsetting-with-the--6-hint-1, eval = FALSE}
... <- ...(10, 3, ..., 5, 8, 1, ...)
```

```{r, include = FALSE}
x2 <- c(10, 3, NA, 5, 8, 1, NA)
```

### 

Subsetting with a logical vector keeps all values corresponding to a TRUE value. This is most often useful in conjunction with the comparison functions.

### Exercise 7

`is.na()` is a function that identifies missing values in vectors, data frames, etc. In the code chunk below, type `x2[]`, placing `is.na(x2)` inside of the brackets.

```{r subsetting-with-the--7, exercise = TRUE}

```

```{r subsetting-with-the--7-hint-1, eval = FALSE}
x2[...(...)]
```

```{r, include = FALSE}
x2[is.na(x2)]
```

### 

This code prints out the missing values (the `NA`'s) stored inside `x2`. Unlike `filter()`, NA indicies will be included in the output as `NA`'s.


### Exercise 8

The modulo operator, `%%`, returns the remainder of the division of two numbers. In the code chunk below, type in `1:10 %% 2` and press "Run Code".  

```{r subsetting-with-the--8, exercise = TRUE}

```

```{r subsetting-with-the--8-hint-1, eval = FALSE}
1:10 ... 2
```

```{r, include = FALSE}
1:10 %% 2
```

### 

This code goes through each integer from 1 to 10 and calculates the remainder when divided by 2. 

### Exercise 9

In the code chunk below, copy the previous code and add `== 0`. Observe the output.

```{r subsetting-with-the--9, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r subsetting-with-the--9-hint-1, eval = FALSE}
1:10 %% 2 ... 0
```

```{r, include = FALSE}
1:10 %% 2 == 0
```

### 

As you can see, the output of this code is a series of `FALSE`'s and `TRUE`'s. This code goes through each integer (from 1 to 10) and checks whether that number (when divided by 2) has a remainder of 0 

In general, if a number divided by 2 produces a remainder of 0, that means it perfectly divisible by 2, meaning that the number is even. This code checks whether each integer is *even*, outputting `TRUE` if it is perfectly divisble and `FALSE` if not.


### Exercise 10


Knowing how to utilize the modulo operator, let's extract all the even values of `x2`. In the code chunk below, type `x2[]`. Inside the brackets, type `x2 %% 2` and equal that expression to `0`, using the `==` operator.

```{r subsetting-with-the--10, exercise = TRUE}

```

```{r subsetting-with-the--10-hint-1, eval = FALSE}
x2[... %% 2 == ...]
```

```{r, include = FALSE}
x2[x2 %% 2 == 0]
```

### 

The `%%` operator is used to calculate the remainder of the division of two numbers. So, by placing `x2 %% 2 == 0` inside the brackets, the code will search through each element of `x2` and return all of the numbers with a remainder of 0 when divided by 2 (thus being an even number). And as mentioned previously, all `NA` indicies will be included in the output as `NA`

### Exercise 11

The last kind of vector that you can subset is a character vector. Using the following vector below, lets extract the `xyz` element. On a new line, type `x3` followed with a pair of brackets, passing in the string `"xyz"`

```{r subsetting-with-the--11, exercise = TRUE}
x3 <- c(abc = 1, def = 2, xyz = 5)
```

```{r subsetting-with-the--11-hint-1, eval = FALSE}
x3 <- c(abc = 1, def = 2, xyz = 5)
x3["..."]
```

```{r, include = FALSE}
x3 <- c(abc = 1, def = 2, xyz = 5)
x3["xyz"]
```

### 

Along with sub-setting logical, character, and integer vectors, you can also subset nothing. For example, by running `x[]` on the code above, it'll just return the vector `x`.

### Exercise 12

Sub-setting can not only be used on vectors; it works on data sets too. In the code chunk below, create a tibble (using `tibble()`) called `df`. The first argument, `x`, should contain a range of numbers from 1 to 3. The second argument, `y`, should be set to the vector `c("a", "e", "f")`. The third argument, `z`, should be set to `runif(3)`. After completing this, run `df` on a new line.

```{r subsetting-with-the--12, exercise = TRUE}

```

```{r subsetting-with-the--12-hint-1, eval = FALSE}
df <- ...(
  ... = 1:3, 
  y = ...("a", "e", "f"), 
  z = ...(3)
)
```

```{r, include = FALSE}
df <- tibble(
  x = 1:3, 
  y = c("a", "e", "f"), 
  z = runif(3)
)
```

### 

There are many ways to use `[` with data sets, but the most common way is to subset by selecting rows and columns, with the syntax `df[row, col]`.

### Exercise 13

Using `df`, let's extract the letter "a". On a new line, type `df` followed by a pair of brackets. In the brackets, type `1,2`.

```{r subsetting-with-the--13, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r subsetting-with-the--13-hint-1, eval = FALSE}
df[... , ...]
```

```{r, include = FALSE}
df[1,2]
```

### 

This extracts the element in the 1st row, 2nd column, which is the letter "a".

### Exercise 14

You can also leave the row/column input blank when extracting data from a data set. For example, `df[rows, ]` returns the specified row(s) and all columns in the data set, while `df[, cols]` returns all rows and the specified column(s) in the data set.

In the code chunk below, extract all the rows in `df`, as well as the columns `x` and `z`.

```{r subsetting-with-the--14, exercise = TRUE}

```

```{r subsetting-with-the--14-hint-1, eval = FALSE}
df[, c("...", "...")]
```

```{r, include = FALSE}
df[, c("x", "z")]

```

### 

As you can see, by leaving the first part of the subset blank (the part before the comma), the code returns all of the rows in `df`, but only returns columns `x` and `z` due to the vector inputted after the comma.

### Exercise 15

There's an important difference between tibbles and data frames when it comes to `[` . In the tutorials, we've mainly used tibbles, which are data frames, but tibbles tweak some behaviors to make your life a little easier. In most places, you can use "tibble" and "data frame" interchangeably, so when we want to draw particular attention to R's built-in data frame, we'll write data.frame.

Press "Run Code".

```{r subsetting-with-the--15, exercise = TRUE}
df1 <- data.frame(x = 1:3)
df2 <- tibble(x = 1:3)

df1
df2
```

### 

If `df` is a data.frame, then `df[, cols]` will return a vector if `col` selects a single column and a data frame if it selects more than one column. If `df` is a tibble, then `[` will always return a \`tibble.

### Exercise 16

Press "Run code".

```{r subsetting-with-the--16, exercise = TRUE}
df0 <- tibble(
  x = c(2, 3, 1, 1, NA), 
  y = letters[1:5], 
  z = runif(5)
)

df0
```

### 

### Exercise 17

The `dplyr` package contains many equivalents of subsetting, such as the `filter()`, `arrange()`, and`select()` functions.

Let's observe the `filter()` equivalent. Pipe `df0` (with the `|>`) to the filter function. Pass `x > 1` into `filter()`.

```{r subsetting-with-the--17, exercise = TRUE}

```

```{r subsetting-with-the--17-hint-1, eval = FALSE}
... |> 
  ...(x > ...)
```

```{r, include = FALSE}
df0 |> 
  filter(x > 1)
```

### 

`filter()` is equivalent to subsetting the rows with a logical vector, taking care to exclude any missing values. For this scenario, the equivalent subset code would be `df0[!is.na(df0$x) & df0$x > 1, ]`. Running this code produces the same result.

### 

The `$` symbol is used to pull out columns from data frames.

### Exercise 18

`arrange()` is equivalent to subsetting the rows with an integer vector, usually created with order(). In the code chunk below, pipe `df0` to `arrange()`, passing in `x, y`. Then, on a new line, paste its equivalent: `df0[order(df0$x, df0$y),]`

```{r subsetting-with-the--18, exercise = TRUE}

```

```{r subsetting-with-the--18-hint-1, eval = FALSE}
... |> 
  ...(x, y)

df0[order(df0$x, df0$y), ]
```

```{r, include = FALSE}
df0 |> 
  arrange(x, y)

df0[order(df0$x, df0$y), ]
```

### 

You can use `order(decreasing = TRUE)` to sort all columns in descending order or `-rank(col)` to sort columns in decreasing order individually.

### Exercise 19

`select()` is equivalent to subsetting columns with character vector. In the code chunk below, pipe `df0` to `select()`, passing in `x, z` to `select()`. Then, on a new line, paste its equivalent: `df0[, c("x", "z")]`

```{r subsetting-with-the--19, exercise = TRUE}

```

```{r subsetting-with-the--19-hint-1, eval = FALSE}
... |>
  ...(x, z)

df0[, c("x", "z")]
```

```{r, include = FALSE}
df0 |>
  select(x, z)

df0[, c("x", "z")]
```

### 

`filter()`, `arrange()`, and `select()` are very useful functions that help organize data. You will use these functions quite often when analyzing data.

## Subsetting with double brackes and a dollar sign
### 

The single bracket operator, `[`, which selects many elements, is paired with the double bracket operator, `[[`, and `$`, which extract a single element. In this section, we'll show you how to use `[[` and `$` to pull columns out of data frames, discuss a couple more differences between data.frames and tibbles, and emphasize some important differences between `[` and `[[` when used with lists.

### Exercise 1

In the code chunk below, create a tibble. The first value should be `x`, which is equal to a range of integers from 1 to 4. The second value should be `y`, which is a vector containing 10, 4, 1, and 21. Save this tibble to the name `tb` and print it on a new line.

```{r subsetting-with-doub-1, exercise = TRUE}

```

```{r subsetting-with-doub-1-hint-1, eval = FALSE}
... <- tibble(x = ..:.., y = c(..., ..., ..., ...))
tb
```

```{r, include = FALSE}
tb <- tibble(x = 1:4, y = c(10, 4, 1, 21))
tb
```

### 

### Exercise 2

The double bracket operator, `[[`, and dollar sign, `$`, can be used to extract columns out of a data frame. `[[` can access by position or by name, and `$` is specialized for access by name.

In the code chunk below, lets extract the elements of column `x`. In the code chunk below, type in `tb` followed by `[[]]`. Inside the inner bracket, type in `1`.

```{r subsetting-with-doub-2, exercise = TRUE}

```

```{r subsetting-with-doub-2-hint-1, eval = FALSE}
tb[[...]]
```

```{r, include = FALSE}
tb[[1]]
```

### 

In this scenario, the `[[]]` are being used to return the values by position. By placing the number `1` inside the brackets, the code returns the values in the first position, which are the range of integers stored in column `x`.

### Exercise 3

Now, lets extract the same elements by name. Copy the code above, replacing the code inside the inner bracket with `"x"`

```{r subsetting-with-doub-3, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r subsetting-with-doub-3-hint-1, eval = FALSE}
tb[["..."]]
```

```{r, include = FALSE}
tb[["x"]]
```

### 

By entering either the position or the name of the column, you can extract the values it contains.

### Exercise 4

As mentioned previously, the `$` is specialized for accessing columns by name. In the code chunk below, lets extract the elements inside `y`. Type in the name of the tibble, `tb`, followed by `$` and the name of the column, `y`.

```{r subsetting-with-doub-4, exercise = TRUE}

```

```{r subsetting-with-doub-4-hint-1, eval = FALSE}
tb...y
```

```{r, include = FALSE}
tb$y
```

### 

As you can see, the `$` extracted the values inside column `y`, which are 10, 4, 1, and 21.

### Exercise 5

The `$` can also be used to create new columns, which is the Base R equivalent of the `mutate()` method. In the code chunk below, type in `tb$z`, setting it equal to `tb$x + tb$y` (use `<-` to do this). On a new line, type in `tb`.

```{r subsetting-with-doub-5, exercise = TRUE}

```

```{r subsetting-with-doub-5-hint-1, eval = FALSE}
tb$z <- ... + ...
tb$z
```

```{r, include = FALSE}
tb$z <- tb$x + tb$y
tb$z
```

### 

There are several other base R approaches to creating new columns including with `transform()`, `with()`, and `within()`. Hadley Wickham, one of the authors of [*R for Data Science*](https://r4ds.hadley.nz/), collected a [few examples](https://gist.github.com/hadley/1986a273e384fb2d4d752c18ed71bedf).

### Exercise 6

Press "Run code".

```{r subsetting-with-doub-6, exercise = TRUE}
diamonds
```

### 

Using `$` directly is convenient when performing quick summaries. Lets use this to calculate some values of the **diamonds** package.

### Exercise 7

Lets find out the maximum carat in the **diamonds** package, using the `max()` function. In the code chunk below, type in `max()`. Inside the parenthesis, type in `diamonds$carat`. 

```{r subsetting-with-doub-7, exercise = TRUE}

```

```{r subsetting-with-doub-7-hint-1, eval = FALSE}
max(...$...)
```

```{r, include = FALSE}
max(diamonds$carat)
```

### 

In this scenario, the code above would be the Base R equivalent of the `summarize()` function.

### Exercise 8

The **dplyr** package also provides a base R equivalent for the double bracket operator, `[[`, and `$` called `pull()`. `pull()` takes either a variable name or variable position and returns just that column.

Let's replicate the code above, using `pull()`. Pipe the **diamonds** package to `pull()`, passing in `carat`. Then, create another pipe to the `max()` function.

```{r subsetting-with-doub-8, exercise = TRUE}

```

```{r subsetting-with-doub-8-hint-1, eval = FALSE}
diamonds |> 
  ...(carat) |> 
    ...()
```

```{r, include = FALSE}
diamonds |> 
  pull(carat) |> 
    max()
```

### 

Just like the previous exercise, the code returns the maximum carat, which is `5.01`.

### Exercise 9

An important difference between tibbles and data frames is that tibbles are much more strict when extracting columns with `$`.

Press "Run code".

```{r subsetting-with-doub-9, exercise = TRUE}
df2 <- data.frame(x1 = 1)
df2$x
```

```{r, include = FALSE}
df2 <- data.frame(x1 = 1)
df2$x
```

### 

Although there is no column named `x` in `df2`, the code is still able to output the values in column `x1`. This is because data frames are able to match the prefix of any variable's name (so-called **partial matching**) without returning an error if the column doesn't exist.

### Exercise 10

However, tibbles are much stricter: they only ever match variable names exactly and they will generate a warning if the column you are trying to access doesn't exist.

Press "Run code".

```{r subsetting-with-doub-10, exercise = TRUE}
tb2 <- tibble(x1 = 1)
tb2$x
```

```{r, include = FALSE}
tb2 <- tibble(x1 = 1)
tb2$x
```

### 

Since there is no column named exactly `x1` in the tibble `tb2`, the code will print warning message and `NULL`. For this reason we sometimes joke that tibbles are lazy and surly: they do less and complain more.

### Exercise 11

The double bracket operator `[[` and dollar sign `$` are really important when working with lists, and have differences compared to the single bracket operator `[`.

Using the `list()` function, create a list. Set the first list element to `a`, which is equal to a range of integers from 1 to 3. Set the second list element to `b`, which is equal to the string `"a string"`. Set the third list element to `c`, which is equal to `pi`, and set the fourth list element to `d`, which is equal to another list containing `-1` and `-5`. Then, set the entire list equal to the variable `list1`.

```{r subsetting-with-doub-11, exercise = TRUE}

```

```{r subsetting-with-doub-11-hint-1, eval = FALSE}
list1 <- ...(
  ... = 1:3, 
  b = "...", 
  c = ..., 
  ... = list(-1, -5)
)
```

```{r, include = FALSE}
list1 <- list(
  a.. = 1:3, 
  b = "a string", 
  c = pi, 
  d = list(-1, -5)
)
```

### 

Remember that the single bracket operator `[` is used to extract sub-components, while the double bracket operator `[[` is used to extract single elements.

### Exercise 12

The `[` can be used to extract a sub-list. In the code chunk below, type in `str()`. Place `list1[1:2]` inside the parenthesis.

```{r subsetting-with-doub-12, exercise = TRUE}

```

```{r subsetting-with-doub-12-hint-1, eval = FALSE}
str(list1[...:...])
```

```{r, include = FALSE}
str(list1[1:2])
```

### 

As you can see, the code returns two lists: one list for `a` and one list for `b`. It doesn't matter how many elements you extract, the result will always be a list.

### Exercise 13

Unlike the single bracket operator, which extracts a sub-list, the double bracket operator, `[[`, extracts a single component from a list.

In the code chunk below, type in `str()`. Inside the function, type in `list1`, followed by double brackets, `[[]]`. Inside the double brackets, type in `4`. `d` is the 4th element inside `list1`, which is why we need to type in `4`.

```{r subsetting-with-doub-13, exercise = TRUE}

```

```{r subsetting-with-doub-13-hint-1, eval = FALSE}
str(list1[[...]])
```

```{r, include = FALSE}
str(list1[[4]])
```

### 

As you can see, the double bracket operator, `[[`, extracts all the components of column `d` in `list1`.

### Exercise 14

Like the double bracket operator, the `$` operator also extracts a single component from a list. 

In the code chunk below, type in `str()`, placing `list1` inside the function. Right next to `list1`, type in `$d`.

```{r subsetting-with-doub-14, exercise = TRUE}

```

```{r subsetting-with-doub-14-hint-1, eval = FALSE}
str(...$...)
```

```{r, include = FALSE}
str(list1$d)
```

### 

With the `$` operator, instead of passing in the element's position (ex: 2nd element is position 2), we pass in the name of the column itself, which in this case is `d`.


The difference between `[` and `[[` is particularly important for lists because `[[` drills down into the list while `[` returns a new, smaller list. Click [here](https://r4ds.hadley.nz/base-r#fig-pepper) to see a visualization of the differences.

## Apply family
### 

In [Chapter 27](https://r4ds.hadley.nz/iteration.html), you learned tidyverse techniques for iteration like `dplyr::across()` and the map family of functions. In this section, you'll learn about their base equivalents, the **apply family**. In this context apply and map are synonyms because another way of saying "map a function over each element of a vector" is "apply a function over each element of a vector". Here we'll give you a quick overview of this family so you can recognize them in the wild.

### Exercise 1

The most important member of this family is `lapply()`. Run `?lapply()` in the console and read the [Description]{.underline} section. CP/CR.

```{r apply-family-1}
question_text(NULL,
	answer(NULL, correct = TRUE),
	allow_retry = TRUE,
	try_again_button = "Edit Answer",
	incorrect = NULL,
	rows = 3)
```

### 

There's no exact base R equivalent to `across()` but you can get close by using `[` with `lapply()`. This works because under the hood, data frames are lists of columns, so calling `lapply()` on a data frame applies the function to each column.

### Exercise 2

The function `sapply()` is very similar to `lapply()`. Run `?sapply()` in the console and read the [Description]{.underline} section. CP/CR.

```{r apply-family-2}
question_text(NULL,
	answer(NULL, correct = TRUE),
	allow_retry = TRUE,
	try_again_button = "Edit Answer",
	incorrect = NULL,
	rows = 3)
```

### 

`sapply()` is similar to `lapply()` but it always tries to simplify the result, hence the "s" in its name.

### Exercise 3

Press "Run code"

```{r apply-family-3, exercise = TRUE}
df4 <- tibble(a = 1, b = 2, c = "a", d = "b", e = 4)
```

### 

We can use the `sapply()` and `lapply()` functions to modify this data.

### Exercise 4

Lets find all the numeric columns in `df4`, using `sapply()`. In the code chunk below, type `sapply()`, passing in `df4` as the first argument and `is.numeric` as the second argument. Save the results to the variable `num_cols`. Then, on a new line, print `num_cols`.

```{r apply-family-4, exercise = TRUE}

```

```{r apply-family-4-hint-1, eval = FALSE}
num_cols <- ...(df4, ...)
```

```{r, include = FALSE}
num_cols <- sapply(df4, is.numeric)
```

### 

As mentioned previously, `sapply()` always tries to simplify the results, hence producing a logical vector instead of a list in the code above. We don't recommend using it for programming, because the simplification can fail and give you an unexpected type, but it's usually fine for interactive use.

### Exercise 5

Now, lets transform each column with `lapply()` and then replace the original values. In the code chunk below, type in `lapply()`. In the first argument, pass in `df4[, num_cols, drop = FALSE]`. In the second column, type in `\(x) x * 2`. Save the results to `df4[, num_cols]`. Then on a new line, type `df4`.

```{r apply-family-5, exercise = TRUE}

```

```{r apply-family-5-hint-1, eval = FALSE}
df4[, ...] <- ...(df4[, ..., ... = FALSE], \(x) x * 2)
```

```{r, include = FALSE}
df4[, num_cols] <- lapply(df4[, num_cols, drop = FALSE], \(x) x * 2)
```

### 

This code transforms each numeric column of `df4` to store the original number multiplied by 2. For example, the original value of column "e" was 4. After running the `lapply()` code, that number has been changed to 8.

### Exercise 6

Base R provides a stricter version of `sapply()` called `vapply()`, short for vector apply. It takes an additional argument that specifies the expected type, ensuring that simplification occurs the same way regardless of the input.

We can replace the `sapply()` code from Exercise 4 with `vapply()`, making sure to specify that `is.numeric()` returns a logical vector of length 1.

On a new line, type in `vapply()`. The first argument should be `df4`, the second argument should be `is.numeric`, and the third argument should be `logical(1)`.

```{r apply-family-6, exercise = TRUE}

```

```{r apply-family-6-hint-1, eval = FALSE}
vapply(... , ... , logical(...))

```

```{r, include = FALSE}
vapply(df4, is.numeric, logical(1))
```

### 

The distinction between `sapply()` and `vapply()` is really important when they're inside a function (because it makes a big difference to the function's robustness to unusual inputs), but it doesn't usually matter in data analysis.

### Exercise 7

Another important member of the apply family is `tapply()` which computes a single grouped summary. Lets use this on the **diamonds** package. In the code chunk below, type in `diamonds` and press "Run Code".

```{r apply-family-7, exercise = TRUE}

```

```{r, include = FALSE}
diamonds
```

### 

If you want to see how you might use `tapply()` or other base techniques to perform other grouped summaries, Hadley has collected a [few techniques](https://gist.github.com/hadley/c430501804349d382ce90754936ab8ec).

### Exercise 8

In the code chunk below, type `tapply()`. The first element should be `diamonds$price`, the second element should be `diamonds$cut`, and the third element should be `mean`. Press "Run Code" after you are done.

```{r apply-family-8, exercise = TRUE}

```

```{r apply-family-8-hint-1, eval = FALSE}
tapply(...$..., ...$..., ...)

```

```{r, include = FALSE}
tapply(diamonds$price, diamonds$cut, mean)
```

### 

Unfortunately `tapply()` returns its results in a named vector which requires some gymnastics if you want to collect multiple summaries and grouping variables into a data frame (it's certainly possible to not do this and just work with free floating vectors, but in our experience that just delays the work).

The final member of the apply family is the titular `apply()`, which works with matrices and arrays, however, this rarely comes up in data science because we usually work with data frames and not matrices.

## For loops
### 

`for` loops are the fundamental building block of iteration that both the *apply* and *map* families use under the hood. `for` loops are powerful and general tools that are important to learn as you become a more experienced R programmer.

The structure for `for` loops looks like this:

```         
for (element in vector) {
  # do something with element
}
```

### Exercise 1

Press "Run Code"

```{r for-loops-1, exercise = TRUE}
L <- list(15, 16, 17, 18, 19)
for (element in L) {
  print(element)
}
```

```{r, include = FALSE}
L <- list(1, 2, 3, 4, 5)
for (element in L) {
  print(element)
}
```

### 

As you can see, the `for` loop iterates through each element in the list, printing out the element.

### Exercise 2

The `sqrt()` is a function that takes the square root of a number. In the code chunk below, type in `sqrt()`, placing the vector `c(4, 16, 121)` inside the parenthesis.

```{r for-loops-2, exercise = TRUE}

```

```{r for-loops-2-hint-1, eval = FALSE}
sqrt(c(... , ... , ...))
```

```{r, include = FALSE}
sqrt(c(4 , 16 , 121))
```

### 

As you can see, the code calculates the square root of each number inside the vector.

### Exercise 3

The `print()` function is used to display the output of code to the console. In the code chunk below, pass in `L1` to the `print()` function.

```{r for-loops-3, exercise = TRUE}
L1 <- list(6, 7, 8, 9, 10)

```

```{r for-loops-3-hint-1, eval = FALSE}
L1 <- list(6, 7, 8, 9, 10)
print(...)
```

```{r, include = FALSE}
L1 <- list(6, 7, 8, 9, 10)
print(L1)
```

### 

As you can see, the `print()` displayed the values inside `L2` in the console.

### Exercise 4

Type in `list()`, placing in the elements `4, 16, 25, 49, 64` inside the parenthesis. Save this to a variable called `L2`.

```{r for-loops-4, exercise = TRUE}

```

```{r for-loops-4-hint-1, eval = FALSE}
... <- list(..., ..., ..., ..., ...)
```

```{r, include = FALSE}
L2 <- list(4, 16, 25, 49, 64)
```

### 

`for()` loops can iterate over many objects, including vectors, tibbles, lists, and dataframes.

### Exercise 5

The most straightforward use of `for` loops is to achieve the same effect as `walk()`: call some function with a side-effect on each element of a list.

Create a `for` loop, placing `element in L2` inside the parenthesis. Inside the loop, type in `print()`, passing in the `sqrt()` function. Inside `sqrt()`, type in `element`.

```{r for-loops-5, exercise = TRUE}

```

```{r for-loops-5-hint-1, eval = FALSE}
for (element in L2) {
  ...(sqrt(...))
}

```

```{r, include = FALSE}
for (element in L2) {
  print(sqrt(element))
}
```

### 

As you can see, the `for` loop goes through each element of `L2` and utilizes the `sqrt()` and `print()` functions to print the square root of each element. `for` loops can be paired with many functions to perform various tasks.

### Exercise 6

Things get tricky if you want to save the output of a `for` loop. Start by creating a `tibble()` with two columns. The first column, called `col1`, should store a `list()` with the numbers `1, 2, 3, 4`. The second column, called `col2`, should store a `list()` with the numbers `11, 12, 13, 14`. Save the result to a variable named `tb4` and print it on a new line.

```{r for-loops-6, exercise = TRUE}

```

```{r for-loops-6-hint-1, eval = FALSE}
... <- tibble(
  ... = list(... , ... , ... , ...),
  col2 = ...(11, ... , ... , ...)
)
```

```{r, include = FALSE}
tb4 <- tibble(
  col1 = list(1, 2, 3, 4),
  col2 = list(11, 12, 13, 14)
)

tb4
```

### 

By using `for` loops, we are able to iterate through data in a tibble and save its output.

### Exercise 7

In order to store output using `for` loops, we will need to use the `vector()` function. In the console, type in `?vector()` and look at the Description section. CP/CR

```{r for-loops-7}
question_text(NULL,
	answer(NULL, correct = TRUE),
	allow_retry = TRUE,
	try_again_button = "Edit Answer",
	incorrect = NULL,
	rows = 3)
```

### 

We will be using the `mode` and `length` arguments of the `vector()` function. In the [Arguments]{.underline} section of `?vector()`, take a look at what these arguments do.

### Exercise 8

There are a few different techniques that you can use to store output with `for` loops, but we recommend being explicit about what the output is going to look like upfront. In this case, we're going to want a list the same length as `tb4`.

In the code chunk below, type in `vector()`. Set the first argument, called `mode`, to `"list"`. Set the second argument, called `length`, to `length(tb4)`. Save the result to the variable `save_data`. Then on a new line, print `save_data`.

```{r for-loops-8, exercise = TRUE}

```

```{r for-loops-8-hint-1, eval = FALSE}
... <- vector(mode = ... , ... = length(...))
```

```{r, include = FALSE}
save_data <- vector(mode = "list", length = length(tb4))
save_data
```

### 

This code produces a vector, which has the same length as `tb4` and is of mode "list". As mentioned previously, we recommend being explicit about what the output is going to look like, which is why we do this step.

### Exercise 9

Now, instead of iterating over the elements of `tb4`, we'll iterate over their indices, using `seq_along()` to generate one index for each element of `tb4`.

In the code chunk below, type `seq_along()`, passing in `tb4`. Save the result to the variable `indexes` and type it on a new line.

```{r for-loops-9, exercise = TRUE}

```

```{r for-loops-9-hint-1, eval = FALSE}
... <- seq_along(...)
```

```{r, include = FALSE}
indexes <- seq_along(tb4)
indexes
```

### 

The `seq_along()` function is being used to generate an index for every element of the `tb4` tibble. As you can see from printing out `indexes`, there are 2 indices created.

### Exercise 10

Now, lets store the contents of `tb4` into `save_data`, with the use of `for` loops. In the code chunk below, create a `for` loop, passing in `i in indexes` in the parenthesis. Inside the `for` loop, type in `tb4[[i]]`. Then, using the `<-` operator, save the code *inside the for loop]* to `save_data[[i]]`.

```{r for-loops-10, exercise = TRUE}

```

```{r for-loops-10-hint-1, eval = FALSE}
for(i in ...) {
  save_data[[...]] <- ...[[i]]
}
```

```{r, include = FALSE}
for(i in indexes) {
  save_data[[i]] <- tb4[[i]]
}
```

### 

Using the `for` loop, the code above iterates through each element of `tb4` and stores it inside `save_data`. Using indices are important because they allows us to link to each position in the input with the corresponding position in the output.

### Exercise 11

Copy the code from the previous exercise. On a new line, type in `save_data` and press "Run Code".

```{r for-loops-11, exercise = TRUE}

```

<button onclick = "transfer_code(this)">Copy previous code</button>

```{r for-loops-11-hint-1, eval = FALSE}
for(i in indexes) {
  save_data[[i]] <- tb4[[i]]
}

save_data

```

```{r, include = FALSE}
for(i in indexes) {
  save_data[[i]] <- tb4[[i]]
}

save_data
```

### 

As you can see, all of the output in `tb4` has been stored inside `save_data`.

## Plots
### 

Many R users who don't otherwise use the tidyverse prefer ggplot2 for plotting due to helpful features like sensible defaults, automatic legends, and a modern look. However, base R plotting functions can still be useful because they're so concise --- it takes very little typing to do a basic exploratory plot.

There are two main types of base plot you'll see in the wild: scatterplots and histograms, produced with `plot()` and `hist()` respectively.

### Exercise 1

Run `?hist()` in the console and look at the **Descripton** section. CP/CR.

```{r plots-1}
question_text(NULL,
	answer(NULL, correct = TRUE),
	allow_retry = TRUE,
	try_again_button = "Edit Answer",
	incorrect = NULL,
	rows = 3)
```

### Exercise 2

Lets use `hist()` and the **diamonds** package to create a histogram. In the code chunk below, type in `hist()`, passing in `diamonds$carat`.

```{r plots-2, exercise = TRUE}

```

```{r plots-2-hint-1, eval = FALSE}

hist(... $ ...)

```

```{r, include = FALSE}
hist(diamonds$carat)
```

### 

As you can see, this code creates a basic histogram of the data in the `carat` column. The `hist()` function would be a quick & easy way to create a histogram of your data.

### Exercise 3

Now lets use the `plot()` function. The `plot()` function creates a scatterplot of the specified data.

In the code chunk below, type in `plot()`, passing in `diamonds$carat` and `diamonds$price`.

```{r plots-3, exercise = TRUE}

```

```{r plots-3-hint-1, eval = FALSE}
plot(...$... , ...$...)
```

```{r, include = FALSE}
plot(diamonds$carat, diamonds$price)
```

### 

Note that base plotting functions work with vectors, so you need to pull columns out of the data frame using `$` or some other technique.

## Summary
### 

This tutorial covered [Chapter 27: A field guide to base R](https://r4ds.hadley.nz/base-r) from [*R for Data Science (2e)*](https://r4ds.hadley.nz/) by Hadley Wickham, Mine Çetinkaya-Rundel, and Garrett Grolemund. \`

In this tutorial, you have learned:

-   how to subset with the single bracket operator, `[`

-   how to subset with the double bracket operator, `[[` and dollar sign, `$`

-   how to use functions from the apply family, such as `lapply()`, `sapply()`, `vapply()`, and `tapply()`

-   how to use `for` loops as a form of iteration

-   how to create plots without **tidyverse** and **ggplot2**

```{r download-answers, child = system.file("child_documents/download_answers.Rmd", package = "tutorial.helpers")}
```
