R Lists

Vectors in R allow one to store many values of the same type (e.g., numerical, logical, strings of text) together in a single variable. Lists allow one to store many different types of data together in a single variable.

For example, we might store a string of text, a single number, and a TRUE/FALSE value in the same list, as shown below:

> my.list = list(name="Paul", height=6, likes.math=TRUE)

> my.list
$name
[1] "Paul"

$height
[1] 6

$likes.math
[1] TRUE

Note, in the example above, the different components are given names (called tags). In this example, the tags are name, height, and likes.math. Tags need not be used, but they are often helpful from a readability standpoint. The example below shows a list defined without explicit tags:

my.list2 = list("Mike", TRUE, "200")

Accessing Elements of a List

One can access the individual elements of a list in a variety of ways, using either the tag name or the position of the element in the list, as shown below:

> my.list = list(name="Paul", height=6, likes.math=TRUE)

> my.list$name
[1] "Paul"

> my.list[["name"]]
[1] "Paul"

> my.list[[1]]   # <-- here we seek the element in position 1 (the first element)
[1] "Paul"

An important restriction on using the double square bracket in this way is that one can only access a single element of the list. So, for example, the following produce errors:

> my.list[[1:2]]
Error in my.list[[1:2]] : subscript out of bounds

> my.list[[c("name","height")]]
Error in my.list[[c("name", "height")]] : subscript out of bounds

Remember, lists can include as elements data of any type -- including lists themselves! In the following example we build a list that contains 3 other lists, a string of text, a logical value, and a vector of 7 elements, and then access it's second element. As one can plainly see, the result is a list.

> listA = list(male.name="Abe",female.name="Alice",ascii.value=65)
> listB = list(male.name="Bob",female.name="Beatrice",ascii.value=66)
> listC = list(male.name="Carl",female.name="Celine",ascii.value=67)

> my.list3 = list(a.things=listA,
+                b.things=listB,
+                c.things=listC,
+                phrase="three amigos",
+                default.response=TRUE,
+                fibonacci.vector=c(1,1,2,3,5,8,13))

> my.list3[["b.things"]]
$male.name
[1] "Bob"

$female.name
[1] "Beatrice"

$ascii.value
[1] 66

> my.list3[["fibonacci.vector"]]
[1]  1  1  2  3  5  8 13

If you want a collection of more than one element of the list, you should use single square brackets instead, which result in a sublist of the list, as the below suggests:

> my.list = list(name="Paul", height="6.0", likes.math=TRUE)

> my.list[1:2]
$name
[1] "Paul"

$height
[1] "6.0"

> my.list[3]
$likes.math
[1] TRUE

Adding and Removing List Elements

One can add an element to a list, even after it has been created. One way this can be done is through the creation of a new tag-value pair, as shown below:

> z = list(a="bob",b=10)  # <-- here we create a list of two elements

> z$c = "figure skating"  # <-- now we add a third element tagged "c"

> z                       # <-- now let's see what's inside list z...
$a
[1] "bob"

$b
[1] 10

$c
[1] "figure skating"

One can also add elements to a list using positions, as the next example shows:

> z = list(a="bob",b=10)        # <-- here we again create a list of two elements

> z[[4]] = 28                   # <-- this adds a fourth element of 28, but since
                                #     there were only 2 elements to begin with, it
                                #     also creates an third element that has no
                                #     real "value", called NULL

> z[5:7] = c(TRUE,TRUE,FALSE)   # <-- this adds a sublist (note the choice of 
                                #     single square brackets) of three more
                                #     elements occupying positions 5, 6, and 7

> z                             # <-- now let's see what's inside list z...
$a
[1] "bob"

$b
[1] 10

[[3]]      # <-- we provided no names/tags for elements at postions 3 through 7 so they
NULL       #     get names of the form [[i]] where i is the position in the list

[[4]]
[1] 28

[[5]]
[1] TRUE

[[6]]
[1] TRUE

[[7]]
[1] FALSE

Removing an element is as easy as setting its tag (or position) to NULL:

> z = list(a="bob",b=1:5,c=10:15,d=FALSE)

> z$b = NULL        # <-- here, we remove the vector (1:5), tagged by "b"

> z[[3]] = NULL     # <-- note the previous removal means that the element
                    #     tagged by "d" is now in position 3.  this removes
                    #     that element

> z                 # <-- with elements tagged "b" and "d" removed, all that
                    #     is left are elements tagged "a" and "c"...
$a
[1] "bob"

$c
[1] 10 11 12 13 14 15

You can also concatenate lists with the c() function, similar to how this is done to vectors:

> list1 = list(TRUE,c(1,2,3),"abc")
> list2 = list("alice","bob",15)

> list3 = c(list1,list2)     # <-- this combines list1 and list 2, storing the result in list3

> list3                      # <-- let's take a look at what's in list3 ...
[[1]]
[1] TRUE

[[2]]
[1] 1 2 3

[[3]]
[1] "abc"

[[4]]
[1] "alice"

[[5]]
[1] "bob"

[[6]]
[1] 15

Useful Functions that Operate on Lists

One can find the size of a list in the same way one gets the size of a vector -- using the length() function:

> list1 = list(TRUE,c(1,2,3),"abc")

> length(list1)
[1] 3

To apply a function to all of the elements of a list, use lapply(). For example, suppose one had a list of two vectors 1:3 and 25:29. To take the median of both, do something similar to the following:

> two.vectors = list(a=1:3,b=25:29)
> lapply(two.vectors,median)
$a
[1] 2

$b
[1] 27

If it is desired to have this output as a vector (or matrix, but more on that later), one can use the sapply() function instead. In case you are curious, "sapply" is short for "simplified (l)apply".

> two.vectors = list(a=1:3,b=25:29)
> sapply(two.vectors,median)
 a  b 
 2 27

Should the function you wish to apply have multiple arguments, and you simply want to consider a vector of values for one of them, leaving the others constant -- R provides a mechanism for doing this as well. As an example, consider the following code, which finds the distance between $x=2$ and several points on the $x$-axis.

dist.between = function(a,b) {
  return(abs(a-b))
}
 
> sapply(-5:5,dist.between,b=2)
 [1] 7 6 5 4 3 2 1 0 1 2 3