+ - 0:00:00
Notes for current slide
Notes for next slide

Miscellaneous Tips and Tricks in R

EC 425/525, Lab 7

Edward Rubin

17 May 2019

1 / 20

Prologue

2 / 20

Schedule

Last time

Simulation in R

Today

Helpful tips and tricks in R

3 / 20

Tips and tricks

4 / 20

Tips and tricks

The apply family

In general, for loops are not the "preferred" route in R.

5 / 20

Tips and tricks

The apply family

In general, for loops are not the "preferred" route in R.

  1. Many functions are vectorized—you can apply a function over a vector.
5 / 20

Tips and tricks

The apply family

In general, for loops are not the "preferred" route in R.

  1. Many functions are vectorized—you can apply a function over a vector.
    E.g., the square root of the numbers from 1 to 10: sqrt(1:10).
5 / 20

Tips and tricks

The apply family

In general, for loops are not the "preferred" route in R.

  1. Many functions are vectorized—you can apply a function over a vector.
    E.g., the square root of the numbers from 1 to 10: sqrt(1:10).

  2. That said, sometimes you just gotta loop.

5 / 20

Tips and tricks

The apply family

In general, for loops are not the "preferred" route in R.

  1. Many functions are vectorized—you can apply a function over a vector.
    E.g., the square root of the numbers from 1 to 10: sqrt(1:10).

  2. That said, sometimes you just gotta loop.
    For these situations, base R offers a family of apply functions.

5 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
  • FUN The function you want to evaluate on each value of X.
6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
  • FUN The function you want to evaluate on each value of X.

lapply() returns a list of the results.

6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
  • FUN The function you want to evaluate on each value of X.

lapply() returns a list of the results.

Example toupper() capitalizes characters

6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
  • FUN The function you want to evaluate on each value of X.

lapply() returns a list of the results.

Example toupper() capitalizes characters, e.g., toupper("a") yields "A".

6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
  • FUN The function you want to evaluate on each value of X.

lapply() returns a list of the results.

Example toupper() capitalizes characters, e.g., toupper("a") yields "A".

lapply(X = c("a", "pig"), FUN = toupper)

6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
  • FUN The function you want to evaluate on each value of X.

lapply() returns a list of the results.

Example toupper() capitalizes characters, e.g., toupper("a") yields "A".

lapply(X = c("a", "pig"), FUN = toupper) returns list("A", "PIG").

6 / 20

Tips and tricks

The apply family

The apply family applies a function over a vector, list, data frame, etc.

For example, lapply() takes two arguments: X and FUN.

  • X A vector/list of values.
  • FUN The function you want to evaluate on each value of X.

lapply() returns a list of the results.

Example toupper() capitalizes characters, e.g., toupper("a") yields "A".

lapply(X = c("a", "pig"), FUN = toupper) returns list("A", "PIG").

Note This is a silly example, as you can directly use toupper() on vectors.

6 / 20

Tips and tricks

Plain apply

The related apply() function applies a given function (FUN) along the margins (MARGIN) of a given array/matrix (X).

7 / 20

Tips and tricks

Plain apply

The related apply() function applies a given function (FUN) along the margins (MARGIN) of a given array/matrix (X).

Your options for MARGIN are 1 for rows and 2 for columns.

7 / 20

Tips and tricks

Plain apply

The related apply() function applies a given function (FUN) along the margins (MARGIN) of a given array/matrix (X).

Your options for MARGIN are 1 for rows and 2 for columns.

Example Let's find the maximum value in each row of a matrix.

# Create a matrix
ex_matrix <- matrix(data = 1:16, nrow = 4, byrow = T)
# Find the maximum value in each row.
apply(X = ex_matrix, MARGIN = 1, FUN = max)
#> [1] 4 8 12 16
7 / 20

Tips and tricks

Multiple apply

Like lapply(), mapply() repeatedly evaluates a function (FUN) for each value in a vector of inputs.

8 / 20

Tips and tricks

Multiple apply

Like lapply(), mapply() repeatedly evaluates a function (FUN) for each value in a vector of inputs.

However, mapply() allows you to evaluate across multiple vectors.

8 / 20

Tips and tricks

Multiple apply

Like lapply(), mapply() repeatedly evaluates a function (FUN) for each value in a vector of inputs.

However, mapply() allows you to evaluate across multiple vectors.

In addition mapply() allows you to dictate whether/how the results are simplified (e.g., SIMPLIFY = T for vector or matrix) or kept as a list.

8 / 20

Tips and tricks

Multiple apply

Like lapply(), mapply() repeatedly evaluates a function (FUN) for each value in a vector of inputs.

However, mapply() allows you to evaluate across multiple vectors.

In addition mapply() allows you to dictate whether/how the results are simplified (e.g., SIMPLIFY = T for vector or matrix) or kept as a list.

Example Random normal draws with different means and variances.

mapply(FUN = rnorm, n = 1, mean = c(0, 10, 20), sd = 1:3)
#> [1] 0.8005418 8.8048199 25.8529457
8 / 20

Tips and tricks

Custom apply

All of our examples used already-defined functions for FUN, e.g.,

9 / 20

Tips and tricks

Custom apply

All of our examples used already-defined functions for FUN, e.g.,

lapply(X = c("a", "pig"), FUN = toupper)
9 / 20

Tips and tricks

Custom apply

All of our examples used already-defined functions for FUN, e.g.,

lapply(X = c("a", "pig"), FUN = toupper)

Alternatively, you define your own function at FUN, e.g.,

9 / 20

Tips and tricks

Custom apply

All of our examples used already-defined functions for FUN, e.g.,

lapply(X = c("a", "pig"), FUN = toupper)

Alternatively, you define your own function at FUN, e.g.,

lapply(X = 1:2, FUN = function(i) {i > 1})
#> [[1]]
#> [1] FALSE
#>
#> [[2]]
#> [1] TRUE
9 / 20

Tips and tricks

Other packages

Other packages offer similar (and parallelized) functions.

base
lapply()
apply()
mapply()

10 / 20

Tips and tricks

Other packages

Other packages offer similar (and parallelized) functions.

base
lapply()
apply()
mapply()

purrr/furrr
map()
?
map2()

10 / 20

Tips and tricks

Other packages

Other packages offer similar (and parallelized) functions.

base
lapply()
apply()
mapply()

purrr/furrr
map()
?
map2()

future.apply
future_lapply()
future_apply()
future_mapply()

10 / 20

Tips and tricks

Other packages

Other packages offer similar (and parallelized) functions.

base
lapply()
apply()
mapply()

purrr/furrr
map()
?
map2()

future.apply
future_lapply()
future_apply()
future_mapply()

parallel
mclapply()
mcapply()
mcmapply()

10 / 20

Tips and tricks

for() loops

However, if you're really committed to running for loops, the syntax is

# Create an empty vector
our_vector <- c()
# Run the for loop for some numbers
for (i in c(1, 1, 2, 3, 5, 8)) {
# Print 'i'
print(i)
# Append 'i' to the end of our_vector
our_vector <- c(our_vector, i)
}
11 / 20

Tips and tricks

Lists and unlisting

Lists (e.g., as outputted by lapply()) can be helpful—but they can also be fairly annoying.

12 / 20

Tips and tricks

Lists and unlisting

Lists (e.g., as outputted by lapply()) can be helpful—but they can also be fairly annoying. Enter unlist().

12 / 20

Tips and tricks

Lists and unlisting

Lists (e.g., as outputted by lapply()) can be helpful—but they can also be fairly annoying. Enter unlist().

List output

lapply(
X = 1:2,
FUN = as.character
)
#> [[1]]
#> [1] "1"
#>
#> [[2]]
#> [1] "2"
12 / 20

Tips and tricks

Lists and unlisting

Lists (e.g., as outputted by lapply()) can be helpful—but they can also be fairly annoying. Enter unlist().

List output

lapply(
X = 1:2,
FUN = as.character
)
#> [[1]]
#> [1] "1"
#>
#> [[2]]
#> [1] "2"

unlist()-ing to vector

lapply(
X = 1:2,
FUN = as.character
) %>% unlist()
#> [1] "1" "2"
12 / 20

Tips and tricks

From lists to data frames

Sometimes you don't want to entirely unlist() a list.

13 / 20

Tips and tricks

From lists to data frames

Sometimes you don't want to entirely unlist() a list.

For example, you might have a list of data frames that you want to bind into a new data frame.

13 / 20

Tips and tricks

From lists to data frames

Sometimes you don't want to entirely unlist() a list.

For example, you might have a list of data frames that you want to bind into a new data frame.

In this case, you can use bind_rows() or bind_cols() from dplyr.

13 / 20

Tips and tricks

From lists to data frames

Sometimes you don't want to entirely unlist() a list.

For example, you might have a list of data frames that you want to bind into a new data frame.

In this case, you can use bind_rows() or bind_cols() from dplyr.

Alternatively, you might be able to make use of map_dfr() or map_dfc().

13 / 20

Tips and tricks

Indexing lists

Also Don't forget that you can index lists using double-brackets.

# Capitalize the alphabet
our_list <- lapply(X = letters, FUN = toupper)
# The third letter
our_list[[3]]
#> [1] "C"
14 / 20

Tips and tricks

Logical vectors and which()

Finally, the simply function which() can be surprisingly helpful.

15 / 20

Tips and tricks

Logical vectors and which()

Finally, the simply function which() can be surprisingly helpful.

which() tells you which of the entries in a logical vector are TRUE

15 / 20

Tips and tricks

Logical vectors and which()

Finally, the simply function which() can be surprisingly helpful.

which() tells you which of the entries in a logical vector are TRUE, i.e., which element—or elements—satisfies your logical condition(s).

15 / 20
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
#> [17] "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
16 / 20
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
#> [17] "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
letters > "m"
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [12] FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [23] TRUE TRUE TRUE TRUE
16 / 20
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
#> [17] "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
letters > "m"
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [12] FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [23] TRUE TRUE TRUE TRUE
which(letters > "m")
#> [1] 14 15 16 17 18 19 20 21 22 23 24 25 26
16 / 20
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
#> [17] "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
letters > "m"
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [12] FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [23] TRUE TRUE TRUE TRUE
which(letters > "m")
#> [1] 14 15 16 17 18 19 20 21 22 23 24 25 26
letters[which(letters > "m")]
#> [1] "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
16 / 20

Alternatively, we could have just used the logical vector.

17 / 20
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
#> [17] "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
18 / 20
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
#> [17] "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
letters > "m"
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [12] FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [23] TRUE TRUE TRUE TRUE
18 / 20
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p"
#> [17] "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
letters > "m"
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [12] FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#> [23] TRUE TRUE TRUE TRUE
letters[letters > "m"]
#> [1] "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
18 / 20

Tips and tricks

Logical vectors, continued

This logic-based selection works on many classes of objects, but it may change the class/structure of the object.

# Create a matrix
mat <- matrix(1:9, ncol = 3)
# Print it out
mat
#> [,1] [,2] [,3]
#> [1,] 1 4 7
#> [2,] 2 5 8
#> [3,] 3 6 9
19 / 20

Tips and tricks

Logical vectors, continued

This logic-based selection works on many classes of objects, but it may change the class/structure of the object.

# Create a matrix
mat <- matrix(1:9, ncol = 3)
# Print it out
mat
#> [,1] [,2] [,3]
#> [1,] 1 4 7
#> [2,] 2 5 8
#> [3,] 3 6 9
# Is the entry even?
mat %% 2 == 0
#> [,1] [,2] [,3]
#> [1,] FALSE TRUE FALSE
#> [2,] TRUE FALSE TRUE
#> [3,] FALSE TRUE FALSE
19 / 20

Tips and tricks

Logical vectors, continued

This logic-based selection works on many classes of objects, but it may change the class/structure of the object.

# Create a matrix
mat <- matrix(1:9, ncol = 3)
# Print it out
mat
#> [,1] [,2] [,3]
#> [1,] 1 4 7
#> [2,] 2 5 8
#> [3,] 3 6 9
# Is the entry even?
mat %% 2 == 0
#> [,1] [,2] [,3]
#> [1,] FALSE TRUE FALSE
#> [2,] TRUE FALSE TRUE
#> [3,] FALSE TRUE FALSE
# Print the even entries
mat[mat %% 2 == 0]
#> [1] 2 4 6 8
19 / 20

Prologue

2 / 20
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow