Learning Objectives: After this chapter you will be able to:
Create a list that holds elements of different types.
Name list elements with names().
Access elements with [[, [, and $.
Explain why [[ returns the element while [ returns a list.
Convert a vector or matrix into a list with as.list().
Convert a list back into a vector with unlist().
9.1 Introduction
Lists are very useful as they are heterogeneous i.e. they can contain different data types. If you remember, vectors and matrices are homogeneous i.e. they can contain only one type of data. If you include different data types, they will all be coerced to the same type. With lists, it is different. In this chapter, we will delve deeper into lists.
9.2 Creating Lists
To create a list, we use the list() function. Let us create a simple list to demonstrate how they can contain different data types.
If you observe the output, all the elements of the list retain their data types. Now let us learn how to access the elements of the list.
9.3 Access List Elements
You can access the elements of a list using the following operators:
[[
[
$
Let us try them one by one.
# using [[l[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
# using [l[1]
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[ extracts the element itself (which may be a vector, matrix, data frame, or nested list), while [ returns a new list containing the selected element(s). The $ operator can be used only when we have named elements in the list. Let us add names to the elements. Use the names() function to add names to the list.
# named elementsnames(l) <-c('vect1', 'vect2', 'vect3', 'mat')l
Knowledge Check:Why use a list at all?vect1 <- 1:10, vect2 <- c('Jack', 'John', 'Jill'), and vect3 <- c(TRUE, FALSE). Why not just c(vect1, vect2, vect3)?
Click to reveal answer
Answer: That would coerce everything to character, because character is the most flexible type. A list keeps each element’s own type.
Explanation:c(vect1, vect2, vect3) gives you c("1", "2", ..., "10", "Jack", ...). Vectors and matrices are homogeneous, so mixing types destroys information. list(vect1, vect2, vect3) stores the three vectors side by side with their types intact.
Knowledge Check:[[ versus [ Given l <- list(1:10, c('Jack', 'John')), what is the difference between l[[1]] and l[1]?
Click to reveal answer
Answer:l[[1]] is the vector 1:10 itself. l[1] is a list containing one element, which is that same vector.
Explanation:[[ extracts the element, so you get the object and can operate on it directly. [ builds a new list holding the selection, which is what you want when you want to delete or keep several elements. Square brackets are for selecting; double square brackets are for extracting.
Knowledge Check:$ needs names Why does l$vect1 fail before you run names(l) <- c('vect1', 'vect2', 'vect3', 'mat')?
Click to reveal answer
Answer: The elements have no names, so there is nothing for $ to match.
Explanation:$ looks up elements by name, not by position. Until the list has names, use l[[1]] or l[1]. Once named, l$vect1 and l[['vect1']] both return the vector.
Knowledge Check:Coercing to a list How do you turn the vector vect1 <- 1:10 into a list, one element per value?
Click to reveal answer
Answer:as.list(vect1), which gives a list of ten single numbers.
Explanation:as.list() splits the vector into its individual elements. The same call works on a matrix, in which case it splits the matrix into columns. The reverse direction is unlist().
Knowledge Check:Flattening a list What does unlist(l, use.names = FALSE) do differently from unlist(l)?
Click to reveal answer
Answer: It returns the same values but without the names.
Explanation:unlist() concatenates every element into one vector and keeps the names it finds, so you get a named vector. Setting use.names = FALSE drops the names, which is usually what you want for further calculation.