Vectors are great, but they have a rule: all elements must be the same type. Real data isn't that tidy. Sometimes you want to bundle a name (character), an age (number), and whether they're enrolled (logical) into one object. That's where lists come in. Lists can hold anything โ numbers, strings, vectors, even other lists.
Creating Lists with list()
Use list() just like c(), but there's no type restriction. Each element can be a completely different type. You can even nest lists inside lists.
# A list with mixed types
student <- list("Alice", 22, TRUE)
print(student)
# Lists can contain vectors and other lists
inventory <- list(
id = 101,
items = c("pen", "notebook"),
in_stock = TRUE
)
print(inventory)
Try it Yourself โ
Named Lists
You can name each element when you create a list. This makes your data self-documenting and access much cleaner. Named lists are the foundation for a lot of R's return values โ many functions give you back a named list.
student <- list(
name = "Alice",
age = 22,
enrolled = TRUE
)
print(student$name)
print(student$age)
Try it Yourself โ
Accessing Elements: $ vs [[]] vs []
Three ways to access list elements, and they behave differently. The $ operator is the simplest โ use it with named elements. Double brackets [[]] return the actual element. Single brackets [] return a sub-list (still a list). This trips up beginners all the time.
student <- list(name = "Alice", age = 22, enrolled = TRUE)
# $ returns the value
student$name
# [[]] also returns the value
student[["name"]]
# [] returns a list (subset)
student["name"]
Try it Yourself โ