2.3 Subsetting Vectors

Quite often we need to select one or more elements from a vector. The subsetting operator [ allows us to do this.

Recall the vector heights:

heights
## Scarecrow    Tinman      Lion   Dorothy      Toto       Boq 
##        72        70        69        58        NA        45

If we want the fourth element, we ask for it with the subsetting operator like this:

heights[4]
## Dorothy 
##      58

If we want two or more elements, then we specify their indices in a vector. Thus, to get the first and fifth elements, we might do this:

desired <- c(1,5)
heights[desired]
## Scarecrow      Toto 
##        72        NA

We could also ask for them directly:

heights[c(1,5)]
## Scarecrow      Toto 
##        72        NA

Negative numbers are significant in subsetting:

heights[-2] #select all but second element
## Scarecrow      Lion   Dorothy      Toto       Boq 
##        72        69        58        NA        45
heights[-c(1,3)]  # all but first and third
##  Tinman Dorothy    Toto     Boq 
##      70      58      NA      45

If you specify a nonexistent index, you get NA, the reasonable result:

heights[7]
## <NA> 
##   NA

Patterned vectors are quite useful for subsetting. If you want the first three elements of heights, you don’t have to type heights[c(1,2,3)]. Instead you can just say:

heights[1:3]
## Scarecrow    Tinman      Lion 
##        72        70        69

The following gives the same as heights:

heights[1:length(heights)]
## Scarecrow    Tinman      Lion   Dorothy      Toto       Boq 
##        72        70        69        58        NA        45

If you desire to quickly provide names for a vector, subsetting can help:

vec <- c(23, 14, 82, 33, 33, 45)
names(vec) <- LETTERS[1:length(vec)]
vec
##  A  B  C  D  E  F 
## 23 14 82 33 33 45

If a vector has names we can refer to its elements using the subsetting operator and those names:

heights["Tinman"]
## Tinman 
##     70
heights[c("Scarecrow", "Boq")]
## Scarecrow       Boq 
##        72        45

Finally, we can use subsetting to modify parts of a vector. For example, Dorothy’s height is reported as:

heights["Dorothy"]
## Dorothy 
##      58

If Dorothy grows two inches, then we can modify her height as follows:

heights["Dorothy"] <- 60

We can replace more than one element, of course. Thus:

heights[c("Scarecrow", "Boq")] <- c(73, 46)

The subset of indices may be as complex as you like:

vec <- c(3,4,5,6,7,8)
vec[seq(from = 2, to = 6, by = 2)] <- c(100, 200, 300)
vec
## [1]   3 100   5 200   7 300

In the above example, seq(2,6,2) identified 2, 4 and 6 as the indices of elements of vec that were to be replaced by the corresponding elements of c(100, 200, 300).

We can even use subsetting to rearrange the elements of a vector. Consider the example below:

inhabitants <- c("Oz", "Toto", "Boq", "Glinda")
permuted <- inhabitants[c(3,4,1,2)]
permuted
## [1] "Boq"    "Glinda" "Oz"     "Toto"

2.3.1 Practice Exercises

We’ll work with the following vector:

practiceVec <- c(4, 3, 7, 10, 5, 3, 8)
  1. Select the fifth element of practiceVec.

  2. Select the third and sixth elements of practiceVec.

  3. Select the first, second, third and fourth elements of practiceVec.

  4. How would you select the last element of the vector mysteryVec if you did not know how many elements it had?

  5. Select all but the fourth element of practiceVec.

  6. Select all but the fourth and sixth elements of practiceVec.

  7. Select the even-numbered elements of practiceVec.

  8. Replace the third element of practiceVec with the number 5.

  9. Replace the even-numbered elements of practiceVec with zeroes.

  10. Replace the second, third and fifth elements of practiceVec with 3, 10, and 20 respectively.

  11. Reverse the order of the elements of practiceVec.

2.3.2 Solutions to Practice Exercises

  1. practiceVec[5]

  2. practiceVec[c(3,6)]

  3. practiceVec[1:4]

  4. mysteryVec[length(mysteryVec)]

  5. practiceVec[-4]

  6. practiceVec[-c(4,5)]

  7. practiceVec[seq(2, length(practiceVec), by = 2)]

  8. practiceVec[3] <- 5

  9. Here is one way:

    zeroes <- rep(0, times = length(seq(2 length(practiceVec))))
    practiceVec[seq(2, length(practiceVec), by = 2)] <- zeroes

    Here’s a quicker way:

    practiceVec[seq(2, length(practiceVec), by = 2)] <- 0

    The latter approach involves “recycling” the zero. We’ll discuss recycling soon.

  10. practiceVec[c(2, 3, 5)] <- c(3, 10, 20)

  11. practiceVec[length(practiceVec):1]