A list is an array of objects, which is to say that the elements in a list are themselves objects. Unlike other data storage types we’ve discussed, the objects in a list can belong to different classes. In short, lists are a collection of objects of different types and lengths.

mylist <- list(10, c("abc", "item"), c(1.23, 1.5, 6), c(TRUE, FALSE))
mylist
## [[1]]
## [1] 10
## 
## [[2]]
## [1] "abc"  "item"
## 
## [[3]]
## [1] 1.23 1.50 6.00
## 
## [[4]]
## [1]  TRUE FALSE

We can examine the contents of a list using str:

Nested Lists

A list can contain all sorts of objects, so why not have a list that contains other lists? These are called nested lists or recursive vectors.

lst2 <- list(1, 3, c("abc", "ABC"), mylist, TRUE)
str(lst2)
## List of 5
##  $ : num 1
##  $ : num 3
##  $ : chr [1:2] "abc" "ABC"
##  $ :List of 4
##   ..$ : num 10
##   ..$ : chr [1:2] "abc" "item"
##   ..$ : num [1:3] 1.23 1.5 6
##   ..$ : logi [1:2] TRUE FALSE
##  $ : logi TRUE

It’s lists all the way down.

Basic Features

Even though lists are a little different from vectors, a lot of the same basic features apply.

Length

This tells us how many objects are in the list, but does not tell us anything about those objects or how many elements might be in each.

We can also use the concatenate function to combine lists, like we used it to combine numbers and strings into vectors.

lst_char <-  list("a", "b", "c")
lst_num <- list(100, 99, 0)
lst <- c(lst_num, lst_char)
str(lst)
## List of 6
##  $ : num 100
##  $ : num 99
##  $ : num 0
##  $ : chr "a"
##  $ : chr "b"
##  $ : chr "c"

Coercion

We can convert vectors and factors to lists using as.list.

v1 <- c(5,9,3.6,4.9,pi)
l1 <- as.list(v1)
str(l1)
## List of 5
##  $ : num 5
##  $ : num 9
##  $ : num 3.6
##  $ : num 4.9
##  $ : num 3.14

How does this conversion take place? What does R do with the vector when turning it into a list?

We can also convert lists to other types using as.*, but this will only work if the conversion is sensible.

as.numeric(l1) # works
## [1] 5.000000 9.000000 3.600000 4.900000 3.141593
# The next line doesn't work.
# You will need to comment this out to knit the document. 
# as.numeric(lst2) 

We can also use unlist, where R will just guess what type of vector is most appropriate.

unlist(l1)
## [1] 5.000000 9.000000 3.600000 4.900000 3.141593
unlist(lst2)
##  [1] "1"     "3"     "abc"   "ABC"   "10"    "abc"   "item"  "1.23"  "1.5"  
## [10] "6"     "TRUE"  "FALSE" "TRUE"

How did R deal with the mix of vector types in lst2?

Testing/Class

As with vectors, we can determine if an object is a list using is.list or class.

is.list(l1)
## [1] TRUE
class(l1)
## [1] "list"

Names

Names start to get more important as we move into lists and matrices because it starts to get more difficult to keep track of what everything means. For example, I might want a list with vectors containing first names, last names, and years of birth.

lst3 <- list(first = c("Dwayne","Nicolas"),
             second = c("Johnson","Cage"),
             birthyear = c(1972,1964))
lst3
## $first
## [1] "Dwayne"  "Nicolas"
## 
## $second
## [1] "Johnson" "Cage"   
## 
## $birthyear
## [1] 1972 1964

Accessing Things from a List

List output is structured to identify each object in the list using [[]] instead of [].

mylist
## [[1]]
## [1] 10
## 
## [[2]]
## [1] "abc"  "item"
## 
## [[3]]
## [1] 1.23 1.50 6.00
## 
## [[4]]
## [1]  TRUE FALSE

We can use this to access objects from the list.

mylist[[2]]
## [1] "abc"  "item"

This isolates that object, which can then be interacted with as an object of whatever type it is:

class(mylist[[2]])
## [1] "character"
# returns the first item from the second object in the list "mylist"
mylist[[2]][1] 
## [1] "abc"

With named lists, we can also access elements using the dollar sign and the desired object’s name:

lst3$second
## [1] "Johnson" "Cage"

On Your Own

Create a list containing a numeric vector named “num1” and a character vector named “cha1”. Then access the first element in cha1 from your list.