Indexing

Author

Marie-Hélène Burle

This section covers indexing from the various data structures.

Indexing atomic vectors

Here is an example with an atomic vector of size one:

Indexing in R starts at 1 and is done with square brackets next to the element to index:

x <- 2
x
[1] 2
x[1]
[1] 2

What happens if we index out of range?

x[2]
[1] NA

Example for an atomic vector with multiple elements:

x <- c(2, 4, 1)
x
[1] 2 4 1
x[2]
[1] 4
x[2:4]
[1]  4  1 NA

Modifying mutable objects

Indexing also allows to modify some of the values of mutable objects:

x
[1] 2 4 1
x[2] <- 0
x
[1] 2 0 1

Copy-on-modify

Not all languages behave the same when you assign the same mutable object to several variables, then modify one of them.

In Python: no copy-on-modify

Don’t try to run this code in R. This is for information only.

Python
a = [1, 2, 3]
b = a
b
[1, 2, 3]
Python
a[0] = 4           # In Python, indexing starts at 0
a
[4, 2, 3]
Python
b
[4, 2, 3]

Modifying a also modifies b: this is because no copy is made when you modify a. If you want to keep b unchanged, you need to assign an explicit copy of a to it with b = copy.copy(a).

In R: copy-on-modify

a <- c(1, 2, 3)
b <- a
b
[1] 1 2 3
a[1] <- 4          # In R, indexing starts at 1
a
[1] 4 2 3
b
[1] 1 2 3

Here, the default is to create a new copy in memory when a is transformed so that b remains unchanged.

Indexing matrices and arrays

x <- matrix(1:12, nrow = 3, ncol = 4)
x
     [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12
x[2, 3]
[1] 8
x <- array(as.double(1:24), c(3, 2, 4))
x
, , 1

     [,1] [,2]
[1,]    1    4
[2,]    2    5
[3,]    3    6

, , 2

     [,1] [,2]
[1,]    7   10
[2,]    8   11
[3,]    9   12

, , 3

     [,1] [,2]
[1,]   13   16
[2,]   14   17
[3,]   15   18

, , 4

     [,1] [,2]
[1,]   19   22
[2,]   20   23
[3,]   21   24
x[2, 1, 3]
[1] 14

Indexing lists

x <- list(2L, 3:8, c(2, 1), FALSE, "string")
x
[[1]]
[1] 2

[[2]]
[1] 3 4 5 6 7 8

[[3]]
[1] 2 1

[[4]]
[1] FALSE

[[5]]
[1] "string"

Indexing a list returns a list:

x[3]
[[1]]
[1] 2 1
typeof(x[3])
[1] "list"

To extract elements of a list, double square brackets are required:

x[[3]]
[1] 2 1
typeof(x[[3]])
[1] "double"

Your turn:

Try to extract the number 7 from this list.

Indexing data frames

x <- data.frame(
  country = c("Canada", "USA", "Mexico"),
  var = c(2.9, 3.1, 4.5)
)
x
  country var
1  Canada 2.9
2     USA 3.1
3  Mexico 4.5

Indexing dataframes can be done by using indices, as we saw for matrices:

x[2, 1]
[1] "USA"

It can also be done using column names thanks to the $ symbol (a column is a vector, so indexing from a column is the same as indexing from a vector):

x$country[2]
[1] "USA"

A data frame is actually a list of vectors representing the various columns:

typeof(x)
[1] "list"

Indexing a column can thus also be done by indexing the element of the list with double square brackets (although this is a slower method).

We get the same result with:

x[[1]][2]
[1] "USA"