The Big R-Book. Philippe J. S. De Brouwer
a <- L$`function`(2,3,pi,5) # to access the function c(…) print(a) ## [1] 2.000000 3.000000 3.141593 5.000000
4.3.6.3 List Manipulations
Since lists can contain objects of different types, it would have been confusing to overload the base operators such as the addition. There are a few other things that make sense.
Lists of Lists Are Also Lists
V1 <- c(1,2,3) L2 <- list(V1, c(2:7)) L3 <- list(L2,V1) print(L3) ## [[1]] ## [[1]][[1]] ## [1] 1 2 3 ## ## [[1]][[2]] ## [1] 2 3 4 5 6 7 ## ## ## [[2]] ## [1] 1 2 3 print(L3[[1]][[2]][3]) ## [1] 4
Note how the list L3
is a list of lists, rather than the concatenation of two lists. Instead of adding the elements of L2 after those of V1 and having nine slots for data, it has two slots. Each of those slots contains the object V1
and L2
respectively.
The double square brackets will inform R that we want one element returned as the most elementary class and is limited to returning one position. The simple square brackets will return a list and can be given a range.
# The first object of L2 as a list: L2[1] ## [[1]] ## [1] 1 2 3 class(L[2]) ## [1] “list” # The first element of L2 is a numeric vector: L2[[1]] ## [1] 1 2 3 class(L2[[2]]) ## [1] “integer” # range L2[1:2] ## [[1]] ## [1] 1 2 3 ## ## [[2]] ## [1] 2 3 4 5 6 7 # Unexpected result (ranges are not to be used with x[[.]]): L2[[1:2]] <- ‘a’ L2 ## [[1]] ## [1] “1” “a” “3” ## ## [[2]] ## [1] 2 3 4 5 6 7 # Is this what you would expect? L2[1:2] <- ‘a’ L2 ## [[1]] ## [1] “a” ## ## [[2]] ## [1] “a”
Add and Delete Elements of a List
A numbered element can be added while skipping positions. In the following example the position 3 is left undefined (NULL).
L <- list(1,2) L[4] <- 4 # position 3 is NULL L ## [[1]] ## [1] 1 ## ## [[2]] ## [1] 2 ## ## [[3]] ## NULL ## ## [[4]] ## [1] 4
Named elements are always added at the end of the list:
L$pi_value <- pi L ## [[1]] ## [1] 1 ## ## [[2]] ## [1] 2 ## ## [[3]] ## NULL ## ## [[4]] ## [1] 4 ## ## $pi_value ## [1] 3.141593
Delete an element by assigning NULL to it:
L[1] <- NULL L ## [[1]] ## [1] 2 ## ## [[2]] ## NULL ## ## [[3]] ## [1] 4 ## ## $pi_value ## [1] 3.141593
It is also possible to delete an element via the squared brackets. Note that if we address the elements of a list by their number, we need to recalculate the numbers. If we were addressing the elements of the list by name, nothing needs to be changed.
L <- L[-2] L ## [[1]] ## [1] 2 ## ## [[2]] ## [1] 4 ## ## $pi_value ## [1] 3.141593
When deleting an element in a list, the numbering will change so that it appears that the deleted element was never there. This implies that when accessing elements of the list by number, it is unsafe to delete elements and can lead to unwanted side effects of the code.
Convert list to vectors
Vectors can only contain one type of variable, while a list can be of mixed types. It might make sense to convert lists to vectors, for example, because some operations on vectors will be significantly faster.
unlist()
To do this R, provides the function unlist()
.
L <- list(c(1:5), c(6:10)) v1 <- unlist(L[1]) v2 <- unlist(L[2]) v2-v1 ## [1] 5 5 5 5 5
Lists are more complex than vectors, instead of failing with a warning and requiring additional options to be set, the unlist()
function will silentlymake some decisions for you.
# A list of vectors of integers: L <- list(1L,c(-10L:-8L)) unlist(L) ## [1] 1 -10 -9 -8 # Note the named real-valued extra element: L <- list(c(1:2),c(-10:-8), “pi_value” = pi) unlist(L) ## ## 1.000000 2.000000 -10.000000 -9.000000 -8.000000 ## pi_value ## 3.141593
Apart from performance considerations, it might also be necessary to convert parts of a list to a vector, because some functions will expect vectors and will not work on lists.
4.3.7 Factors
Factors are the objects which hold a series of labels. They store the vector along with the distinct values of the elements in the vector as label. Factors are in many ways similar to the enum
data type in C, C++ or Java, here they aremainly used to store named constants. The labels are always of the character-type2 irrespective of data type of the elements in the input vector.
factors
4.3.7.1 Creating Factors
Factors are created using factor()
the function.
factor()
# Create a vector containing all your observations: feedback <- c(‘Good’,‘Good’,‘Bad’,‘Average’,‘Bad’,‘Good’) # Create a factor object: factor_feedback <- factor(feedback) # Print the factor object: print(factor_feedback) ## [1] Good Good Bad Average Bad Good ## Levels: Average Bad Good
From the aforementioned example it is clear that the factor-object “is aware” of all the labels for all observations as well as the different levels (or different labels) that exist. The next code fragment makes clear that some functions – such as plot()
– will recognize the factor-object and produce results that make sense for this type of object. The following line of code is enough to produce the output that is shown in Figure 4.1.
# Plot the histogram -- note the default order is alphabetic plot(factor_feedback)
Figure 4.1: The plot-function will result in a bar-chart for a factor-object.
There