Model results, JSON data and data frames are all lists, so you meet them constantly.
A list is a vector whose elements can be anything: numbers, strings, functions, data frames, other lists. Create one with list(name = "Ana", scores = c(90, 85), tags = list("a", "b")).
The crucial distinction is between [ and [[:
l[1]orl["name"]returns a sub-list (still a list, a train with fewer carriages).l[[1]]orl[["name"]]returns the element itself (the contents of one carriage).l$nameis shorthand forl[["name"]]and is what you use interactively.
Assigning l$new <- value adds an element and l$old <- NULL removes one. To store an actual NULL, use l["key"] <- list(NULL).
str(l) is the best way to see the structure of any list: it shows each element's type, length and first values. names(l) lists the names, length(l) counts the elements.
Lists nest naturally, so config$db$host drills down. Many functions return lists: lm() gives a model object that is a list with a class, and jsonlite::fromJSON turns JSON objects into lists. unlist() flattens a list into an atomic vector, coercing types as it goes.
Example
person <- list(name = "Ana", scores = c(90, 85), address = list(city = "Yerevan"))
str(person)
#> List of 3
#> $ name : chr "Ana"
#> $ scores : num [1:2] 90 85
#> $ address:List of 1
#> ..$ city: chr "Yerevan"
print(class(person["scores"])) #> [1] "list"
print(class(person[["scores"]])) #> [1] "numeric"
print(mean(person$scores)) #> [1] 87.5
print(person$address$city) #> [1] "Yerevan"
person$email <- "ana@example.com" # add
person$address <- NULL # remove
print(names(person)) #> [1] "name" "scores" "email"
print(unlist(list(a = 1, b = 2:3)))
#> a b1 b2
#> 1 2 3Remember
[returns a sub-list,[[and$return the element- Assigning NULL removes an element
- Use
str()to inspect any nested structure
Watch out for
- Using
l[1]and then trying arithmetic on it: it's still a list, usel[[1]].