Lists are a step up in complexity from atomic vectors: each element can be any type, not just vectors. Technically speaking, each element of a list is actually the same type because, as you saw in Section 2.3.3, each element is really a reference to another object, which can be any type.
You construct lists with
list( l1 <-1:3, "a", c(TRUE, FALSE, TRUE), c(2.3, 5.9) ) typeof(l1) #>  "list" str(l1) #> List of 4 #> $ : int [1:3] 1 2 3 #> $ : chr "a" #> $ : logi [1:3] TRUE FALSE TRUE #> $ : num [1:2] 2.3 5.9
Because the elements of a list are references, creating a list does not involve copying the components into the list. For this reason, the total size of a list might be smaller than you might expect.
::obj_size(mtcars) lobstr#> 7,208 B list(mtcars, mtcars, mtcars, mtcars) l2 <-::obj_size(l2) lobstr#> 7,288 B
Lists can contain complex objects so it’s not possible to pick a single visual style that works for every list. Generally I’ll draw lists like vectors, using colour to remind you of the hierarchy.
Lists are sometimes called recursive vectors because a list can contain other lists. This makes them fundamentally different from atomic vectors.
list(list(list(1))) l3 <-str(l3) #> List of 1 #> $ :List of 1 #> ..$ :List of 1 #> .. ..$ : num 1
c() will combine several lists into one. If given a combination of atomic vectors and lists,
c() will coerce the vectors to lists before combining them. Compare the results of
list(list(1, 2), c(3, 4)) l4 <- c(list(1, 2), c(3, 4)) l5 <-str(l4) #> List of 2 #> $ :List of 2 #> ..$ : num 1 #> ..$ : num 2 #> $ : num [1:2] 3 4 str(l5) #> List of 4 #> $ : num 1 #> $ : num 2 #> $ : num 3 #> $ : num 4
3.5.2 Testing and coercion
typeof() a list is
list. You can test for a list with
is.list(), and coerce to a list with
list(1:3) #> [] #>  1 2 3 as.list(1:3) #> [] #>  1 #> #> [] #>  2 #> #> [] #>  3
You can turn a list into an atomic vector with
unlist(). The rules for the resulting type are complex, not well documented, and not always equivalent to what you’d get with
3.5.3 Matrices and arrays
With atomic vectors, the dimension attribute is commonly used to create matrices. With lists, the dimension attribute can be used to create list-matrices or list-arrays:
list(1:3, "a", TRUE, 1.0) l <-dim(l) <- c(2, 2) l#> [,1] [,2] #> [1,] Integer,3 TRUE #> [2,] "a" 1 1, 1]] l[[#>  1 2 3
These data structures are relatively esoteric but they can be useful if you want to arrange objects in a grid-like structure. For example, if you’re running models on a spatio-temporal grid, it might be more intuitive to store the models in a 3D array that matches the grid structure.
List all the ways that a list differs from an atomic vector.
Why do you need to use
unlist()to convert a list to an atomic vector? Why doesn’t
Compare and contrast
unlist()when combining a date and date-time into a single vector.