More on Lists

(Section 9.3)

Application: Splitting

Sub-setting by seat:

Here’s a slow, annoying way:

Sub-setting with split()

Here’s a cool way:

One Hitch

This won’t work to get at one of the frames (try it):

1_front is not a legal name for a variable. (Cannot begin with a number!)

No Big Deal

You can do this:

Or this:

Appliction: Storing Results in a List

Back to the Flowery Meadow

Recall the flowers in the meadow:

flower_colors <- c("blue", "red", "pink", "crimson", "orange")

Our goal: store results of all walks in a list.

Helper-Function:

walk_meadow_vec <- function(color, wanted) {
  picking <- TRUE
  ## the following will be extended to hold the flowers picked:
  flowers_picked <- character()
  desired_count <- 0
  while (picking) {
    picked <- sample(flower_colors, size = 1)
    flowers_picked <- c(flowers_picked, picked)
    if (picked == color) desired_count <- desired_count + 1
    if (desired_count == wanted) picking <- FALSE
  }
  ## return the vector of flowers picked:
  flowers_picked
}

Try it Out

Function to Make the List

all_walk_list <- function(people, favs, numbers) {
  ## initialize a list of the required length:
  lst <- vector(mode = "list", length = length(people))
  for (i in 1:length(people)) {
    fav <- favs[i]
    number <- numbers[i]
    lst[[i]] <- walk_meadow_vec(
      color = fav,
      wanted = number
    )
  }
  ## give names:
  names(lst) <- people
  ## return the list
  lst
}

Try it out

Application: Returning Multiple Items

Some Cool Functions

nchar() returns the number of characters in a string:

nchar("Dorothy")
[1] 7

toupper() makes all the letters of a string upper-case:

toupper("Dorothy")
[1] "DOROTHY"

Simple Function # 1

This function takes two strings and returns the number of characters in each:

Simple Function # 2

This function takes two strings and returns the upper-case versions of each:

Simple Function #3

We would like a function that takes a string and returns:

  • the number of characters in it, and
  • the upper-case version of it.

Problem

"7" is a string, not a number!

Also a Problem

We only get the string!

And Still a Problem

We only get the number!

Solution

Return a list!

Understanding Ellipses

What is ...?

The Ellipsis Argument

... stands for “any other arguments you want to add”:

Application

Remember the na.rm parameter of functions like mean():

vec <- c(2,5,4,6,NA)
mean(vec)
[1] NA
mean(vec, na.rm = TRUE)
[1] 4.25

A Function to Compute Several Means

manyMeans <- function(vecs = list()) {
  n <- length(vecs)
  if ( n == 0 ) {
    return(cat("Need some vectors to work with!"))
  }
  results <- numeric(n)
  for (i in 1:n) {
    results[i] <- mean(vecs[[i]])
  }
  results
}

Try It Out

manyMeans(list(1:5, 6:10))
[1] 3 8
manyMeans(list(1:5, c(6,7,8,9,NA)))
[1]  3 NA

Use na.rm = TRUE

manyMeans <- function(vecs = list()) {
  n <- length(vecs)
  if ( n == 0 ) {
    return(cat("Need some vectors to work with!"))
  }
  results <- numeric(n)
  for ( i in 1:n ) {
    results[i] <- mean(vecs[[i]], na.rm = TRUE)
  }
  results
}
manyMeans(list(1:5, c(6,7,8,9,NA)))
[1] 3.0 7.5

But this decides the option for the user! Can we let the user decide?

Solution: Use Ellipsis Argument

manyMeans <- function(vecs = list(), ...) {
  n <- length(vecs)
  if ( n == 0 ) {
    return(cat("Need some vectors to work with!"))
  }
  results <- numeric(n)
  for ( i in 1:n ) {
    results[i] <- mean(vecs[[i]], ...)
  }
  results
}

Try It Out