EthicsComputerCourses
Join training +91 90532 10052

Lists

R Programming · Lesson 8 of 29 Beginner 6 min read Updated

A vector holds values of one type only. Real records are messier: a student has a name (text), an age (number), several marks (a numeric vector) and a hostel status (TRUE or FALSE). A list can hold all of these together, each element keeping its own type and length. Lists are R's general-purpose container, and many functions, including statistical tests and models, return their results as lists.

In this lesson you will create lists, learn the difference between [ ], [[ ]] and $, change and remove elements, and work with lists inside lists.

Creating a list

Use list() and give each element a name:

RTry it yourself
student <- list(name = "Kabir", age = 20, marks = c(78, 84, 69), hostel = FALSE)
student
length(student)
names(student)
Output
$name
[1] "Kabir"

$age
[1] 20

$marks
[1] 78 84 69

$hostel
[1] FALSE

[1] 4
[1] "name"   "age"    "marks"  "hostel"

Each element prints under its name with a $ in front. The list has four elements, even though one of them, marks, holds three numbers. Names are optional but strongly recommended: student$marks is far clearer than "element number 3".

[ ] versus [[ ]] and $

This is the most important idea in this lesson. Think of a list as a train and each element as a coach carrying passengers.

  • student["marks"] with single brackets gives you a smaller train: a list containing just that coach.
  • student[["marks"]] with double brackets gives you the passengers: the value inside the coach.
  • student$marks is a shortcut for student[["marks"]].
RTry it yourself
student <- list(name = "Kabir", age = 20, marks = c(78, 84, 69), hostel = FALSE)
student["marks"]
class(student["marks"])
student[["marks"]]
class(student[["marks"]])
student$marks[2]
mean(student$marks)
Output
$marks
[1] 78 84 69

[1] "list"
[1] 78 84 69
[1] "numeric"
[1] 84
[1] 77

mean(student["marks"]) would fail with a warning and return NA, because you cannot average a list. mean(student$marks) works because $ gives the numeric vector inside. Use [ ] when you want to keep a list (for example, several elements at once: student[c("name", "age")]), and [[ ]] or $ when you want the value itself.

[[ ]] also accepts a variable holding the name, which $ cannot do:

R
field <- "age"
student[[field]]    # 20
student$field       # NULL: looks for an element literally called "field"

Changing, adding and removing elements

Assign to an element to change it or add a new one. Assign NULL to remove it. str() (structure) gives a compact one-line-per-element view, which is the best way to look at a list:

RTry it yourself
student <- list(name = "Kabir", age = 20, marks = c(78, 84, 69))
student$city <- "Lucknow"
student$age <- NULL
str(student)
Output
List of 3
 $ name : chr "Kabir"
 $ marks: num [1:3] 78 84 69
 $ city : chr "Lucknow"

str() shows each element's name, type (chr for character, num for numeric) and its first values. Use it on any unfamiliar object; you will use it on data frames and model results too.

Lists inside lists

An element of a list can itself be a list, which lets you store structured records. Here is a train with its stops and its coaches:

RTry it yourself
train <- list(
  number = 12951,
  name = "Mumbai Rajdhani",
  stops = c("Mumbai Central", "Surat", "Vadodara", "Kota", "New Delhi"),
  coaches = list(ac_first = 1, ac_two = 5, ac_three = 11)
)
train$stops[length(train$stops)]
train$coaches$ac_three
train[["coaches"]][["ac_two"]]
unlist(train$coaches)
sum(unlist(train$coaches))
Output
[1] "New Delhi"
[1] 11
[1] 5
ac_first   ac_two ac_three 
       1        5       11 
[1] 17
  • Chain $ to go deeper: train$coaches$ac_three.
  • [[ ]] can be chained the same way.
  • unlist() flattens a list into a plain vector, so you can use vector functions like sum() on it. It only makes sense when all the values are of one type, otherwise everything is coerced to text.

The coach numbers here are invented for practice.

Where you will meet lists

You will use lists constantly even if you never create one yourself:

  • A data frame is a special list in which every element is a column of the same length. That is why df$column works.
  • Statistical tests and models return lists. In Hypothesis Tests you will pull the p-value out of a test result with $p.value.
  • Functions that must return several values return a list, as you will see in Functions.
  • lapply() returns a list, as you will see in The apply Family.

Common mistakes

  • Using [ ] when you need the value. student["marks"] is a list; sum() and mean() need student[["marks"]] or student$marks.
  • Using $ with a variable. student$field does not look up the name stored in field; use student[[field]].
  • Removing with NA instead of NULL. student$age <- NA keeps the element with a missing value; NULL removes it.
  • Calling unlist() on mixed types. Numbers become text when mixed with text.

Key points

  • A list holds elements of any type and length, usually with names.
  • [ ] returns a smaller list; [[ ]] and $ return the value inside an element.
  • Assign to add or change an element; assign NULL to remove it.
  • str() shows the structure of a list compactly; unlist() flattens it into a vector.
  • Data frames, model results and test results are all lists underneath.

Exercise

Create a list for a shop order with these elements: customer ("Meera"), items (a named vector of prices: dosa batter 90, curd 45, bananas 60) and delivered (FALSE). Print the total of the items, mark the order as delivered, add a city element ("Kochi"), and show the final structure with str().

Show solution
R
order <- list(customer = "Meera",
              items = c(dosa_batter = 90, curd = 45, bananas = 60),
              delivered = FALSE)
sum(order$items)
order$delivered <- TRUE
order$city <- "Kochi"
str(order)
Output
[1] 195
List of 4
 $ customer : chr "Meera"
 $ items    : Named num [1:3] 90 45 60
  ..- attr(*, "names")= chr [1:3] "dosa_batter" "curd" "bananas"
 $ delivered: logi TRUE
 $ city     : chr "Kochi"

order$items is a named numeric vector, so sum() works on it directly. str() also shows the names attribute of that vector on an extra line.

Quick Quiz

1. x <- list(a = 1:3, b = "hi"). What is class(x["a"])?

2. Which expression returns the numbers stored in element a?

3. How do you remove element b from the list x?

4. What does unlist(list(a = 1, b = 2)) return?

Learn R Programming with a mentor

Free lessons get you started. Our Data Science & Machine Learning training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call