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")
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
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 positions 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
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