17 Lists
In this chapter, you will learn about R lists, the most generic type of data container in R.
- Lists are the most general class of data container
- Like vectors, lists group data into a one-dimensional set
- Unlike vectors, lists can store all kinds of objects
- Lists can be of any length
- Elements of a list can be named, or not
17.1 Creating Lists
The typical way to create a list is with the function list()
. This function
creates a list the same way c()
creates a vector. Let’s start with a simple
example creating three numeric vectors of same length, that we then use to
store them in a list:
vec1 <- 1:3
vec2 <- 4:6
vec3 <- 7:9
# list with unnamed elements
lis <- list(vec1, vec2, vec3)
lis
#> [[1]]
#> [1] 1 2 3
#>
#> [[2]]
#> [1] 4 5 6
#>
#> [[3]]
#> [1] 7 8 9
Note how the contents of a list with unnamed elements are displayed: there is a set of double brackets with an index indicating the position of each element, and below each double bracket the corresponding vector is printed.
For illustration purposes, we could visualize the three input vectors and the list with the following conceptual diagram.
Our intention with the depicted list as a set of discontinuous cells is to convey the idea that a list is also a one-dimensional vector, albeit a very special type of vector: a non-atomic vector. This means that each element of a list can be any kind of object.
In the same way you can give names to elements of a vector, you can also give names to elements of a list:
# list with named elements
lis <- list("vec1" = vec1, "vec2" = vec2, "vec3" = vec3)
lis
#> $vec1
#> [1] 1 2 3
#>
#> $vec2
#> [1] 4 5 6
#>
#> $vec3
#> [1] 7 8 9
When you create a list in this form, you can actually omit the quotes of the given names. While this option of naming elements may create a bit of confusion for beginners and inexperienced users in R, we believe it’s not a big deal (based on our experience):
# another option for giving names to elements in a list
lis <- list(vec1 = vec1, vec2 = vec2, vec3 = vec3)
lis
#> $vec1
#> [1] 1 2 3
#>
#> $vec2
#> [1] 4 5 6
#>
#> $vec3
#> [1] 7 8 9
Observe how the contents of a list with named elements are displayed: now,
instead of the set of double brackets, there is a dollar sign followed by the
name of the element, e.g. $vec1
. Below each name, the corresponding vector is
printed.
The conceptual diagram in this case could look like this:
As we just said, the elements of a list can be any kind of R object. For
example, here’s a list called lst
that contains a character vector, a
numeric matrix, a factor, and another list:
lst <- list(
c("Harry", "Ron", "Hermione"),
matrix(1:6, nrow = 2, ncol = 3),
factor(c("yes", "no", "no", "no", "yes")),
list("Harry", "Ron", "Hermione")
)
lst
#> [[1]]
#> [1] "Harry" "Ron" "Hermione"
#>
#> [[2]]
#> [,1] [,2] [,3]
#> [1,] 1 3 5
#> [2,] 2 4 6
#>
#> [[3]]
#> [1] yes no no no yes
#> Levels: no yes
#>
#> [[4]]
#> [[4]][[1]]
#> [1] "Harry"
#>
#> [[4]][[2]]
#> [1] "Ron"
#>
#> [[4]][[3]]
#> [1] "Hermione"
Whenever possible, we strongly recommend giving names to the elements of a list. Not only this makes it easy to identify one element from the others, but it also gives you more flexibility to rearrange the contents of the list without having to worry about the exact order or position they occupy.
17.2 Manipulating Lists
To manipulate the elements of a list you can use bracket notation. Because a
list is a vector, you can use single brackets (e.g. lis[1]
) as well as
double brackets (e.g. lis[[1]]
).
17.2.1 Single brackets
Just like any other vector, and any other data object in R, you can use single
brackets on a list. For example, consider the unnamed version of a list, and
the use of single brackets with index 1
inside them:
What a single bracket does, is give you access to the “container” of the
specified element but without “unboxing” its contents. This is reflected by
the way in which the output is displayed: note the double bracket [[1]]
in
the first line, and then [1] 1 2 3
in the second line.
In other words, lis[1]
gives you the first element of the list, which
contains a vector, but it does not give you direct access to the vector itself.
Put another way, lis[1]
lets you see that the first element of the list is
a vector, but this vector is still inside its “box”.
17.2.2 Double Brackets
In addition to single brackets, lists also accept double brackets: e.g.
lis[[1]]
Double brackets are used when you want to get access to the content of the
list’s elements. Notice the output of the previous command: now there are no
double brackets, just the output of the vector in the first position. Think
of this command as “unboxing” the object of the first element in lis
.
What if you want to manipulate the elements of vector vec1
or vec2
? Use
double brackets followed by single brackets
# second index of first list's element
lis[[1]][2]
#> [1] 2
# first index of second list's element
lis[[2]][1]
#> [1] 4
17.2.3 Dollar signs
R lists—and data frames—follow an optional second system of notation for
extracting named elements using the dollar sign $
Let’s use the named version of lis
:
# list with named elements
lis <- list("vec1" = vec1, "vec2" = vec2, "vec3" = vec3)
lis$vec1
#> [1] 1 2 3
The dollar sign $
notation works for selecting named elements in a
list. Notice the output of the above command: lis$vec1
gives you vector
1 2 3
. In other words, dollar notation “unboxes” the object that is associated
to the specified name.
17.2.4 Adding new elements
From time to time, you will want to add one or more elements to an existing
list. For instance, consider a list lst
with two elements:
Say you want to add a logical vector as a third element to lst
. One option to
do this is with double brackets, specifying a new index position to which you
assign the new element:
lst[[3]] <- c(TRUE, FALSE, TRUE, FALSE)
lst
#> [[1]]
#> [1] 1 2 3
#>
#> [[2]]
#> [1] "A" "B" "C"
#>
#> [[3]]
#> [1] TRUE FALSE TRUE FALSE
Another option is to use the dollar operator by giving a new name to which you
assign the new element. Even though the previous elements in lst
are unnamed,
the new added element will have an associated label:
17.2.5 Removing elements
Just like you will want to add new elements in a list, you will also find
occasions in which you need to remove one or more elements. Take the previous
list lst
with four elements, and say you want to remove the third element
(containing the logical vector)
lst
#> [[1]]
#> [1] 1 2 3
#>
#> [[2]]
#> [1] "A" "B" "C"
#>
#> [[3]]
#> [1] TRUE FALSE TRUE FALSE
#>
#> $new_elem
#> [1] "nuevo"
To remove the third element, which is unnamed, you use double brackets and
assign a value NULL
to that position:
lst[[3]] <- NULL
lst
#> [[1]]
#> [1] 1 2 3
#>
#> [[2]]
#> [1] "A" "B" "C"
#>
#> $new_elem
#> [1] "nuevo"
As for those named elements, such as lst$new_elem
, you do the same and assign
a NULL
value, but this time using dollar notation:
17.2.6 Slides
17.3 Exercises
1) How would you create a list with your first name, middle name, and last name? For example, something like:
$first
[1] "Gaston"
$middle
NULL
$last
[1] "Sanchez"
2) Consider an R list student
containing the following elements:
$name
[1] "Luke Skywalker"
$major_minor
major minor
"jedi studies" "imperial policies"
$gpa
[1] 4
$grades
course score
1 force-101 9.3
2 light-sabers 10.0
3 jedi-literature 8.5
What is the output of the following commands? Try to guess the answer without running the code.
student$grades$semester <- 4
sum(student[[2]] == "sith philosophy")
student["sid"] <- as.integer("123456")
mean(student[[4]][1:3,2], na.rm = TRUE)
student[[4]] <- student$grades[c(FALSE, TRUE, TRUE), ]