Creating Lists

Lists place essentially no restrictions on the nature of their contents:

So, lists are a great way to store substantively related, but heterogeneously sized/typed, pieces of data in one object.

Generating Lists

We construct lists using the list() function.

(l1 <- list(1, 2, 3))
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3
(l2 <- list("bob", TRUE, 33, 42 + 3i))
[[1]]
[1] "bob"

[[2]]
[1] TRUE

[[3]]
[1] 33

[[4]]
[1] 42+3i
(l3 <- list(c(1, 2), c(3, 4)))
[[1]]
[1] 1 2

[[2]]
[1] 3 4
Practice

Create a list called myList that comprises the following three elements.

  1. A length-three numeric vector
  2. A length-one character vector
  3. A length-two logical vector

Here’s one possible solution.

myList <- list(
  1:3,
  "alice is not bob",
  rep(TRUE, 2)
)

myList
[[1]]
[1] 1 2 3

[[2]]
[1] "alice is not bob"

[[3]]
[1] TRUE TRUE

Naming List Elements

We can name the elements of a list by defining the list slots via key-value pairs.

l4 <- list(
  name = "bob",
  alive = TRUE,
  age = 33,
  relationshipStatus = 42 + 3i
)

l4
$name
[1] "bob"

$alive
[1] TRUE

$age
[1] 33

$relationshipStatus
[1] 42+3i

We can use the names() function to access and modify the names of a list’s slots.

# The slots in l1 don't yet have names
names(l1)
NULL
l1
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3
# Add names to the l1 slots
names(l1) <- c("first", "second", "third")
l1
$first
[1] 1

$second
[1] 2

$third
[1] 3

The names() function returns a character vector. So, we can assign/overwrite a subset of the names using ordinary vector subsetting syntax.

# Change the name for the second slot in l4
names(l4)[2] <- "not dead"
names(l4)
[1] "name"               "not dead"           "age"               
[4] "relationshipStatus"
l4
$name
[1] "bob"

$`not dead`
[1] TRUE

$age
[1] 33

$relationshipStatus
[1] 42+3i
Practice

Consider the following list (aList) when answering this question.

aList
$hello
[1] "world"

$day
[1] "monday"

$name
[1] "jude"

$false
[1] TRUE

Predict what the following code will print.

names(aList)[2:3] <- c("blue", "hey")
aList

Use the interactive editor to check your predictions.

We’ve overwritten the names of the second and third list slots with the new values blue and hey, respectively. So, we see an updated version of aList that contains the same data but has two new names.

$hello
[1] "world"

$blue
[1] "monday"

$hey
[1] "jude"

$false
[1] TRUE

Nested Lists

It’s difficult to overstate the versatility of lists as general-purpose containers for R objects. It’s no exaggeration to say that a list can store any type of R object. Notably, lists are perfectly happy to store other lists. So the following abomination is a completely valid list.

level0 <- list(
    level1 = list(
        level2a = list(
            level3a = list("How much wood"),
            level3b = list("would a woodchuck chuck"),
            level3c = list("if")
        ),
        level2b = list(
            level3a = list("a"),
            level3b = list("woodchuck could"),
            level3c = list("chuck wood?")
        )
    )
)
Practice

Create a list to describe yourself. Include the following named elements in your list:

  1. Your Name
  2. Your Eye Color
  3. Your Hair Color
  4. Your Favorite Color
myInfo <- list(
  name = "bob",
  eyes = "blue",
  hair = "black",
  color = "green"
)

myInfo
$name
[1] "bob"

$eyes
[1] "blue"

$hair
[1] "black"

$color
[1] "green"
Knowledge Check
  • What’s the key difference between a list slot and a vector element, in terms of what kind of data each can hold?
  • If you don’t name a list’s slots when you generate the list, can you still add names later later? How?
Back to top