Yihui Xie

x[matrix(ncol = 2)]

Do I really know base R?!

Yihui Xie / 2017-11-02


Karl Broman was surprised that x[[c(5, 3)]] in R was the same as x[[5]][[3]]. And it was in 2013. It reminded me of a similar thing that surprised me a couple of months ago. I have used R for more than 10 years, and for the first time I had discovered that for a matrix x and a two-column integer index matrix i (each row of i is a pair of row and column indices to index x), x[i] returns the vector c(x[i[1, 1], i[1, 2]], x[i[2, 1], i[2, 2]], ..., x[i[n, 1], i[n, 2]]). Actually I had been searching for this way of indexing for years, and I didn’t know it was this simple! In the past, I was using an awkward loop like:

n = nrow(i)
y = numeric(n)
for (k in seq_len(n)) {
  y[k] = x[i[k, 1], i[k, 2]]
}
y

That was both ugly and inefficient. After someone asked me this question again a couple of months ago, I came up with a slightly more elegant solution but perhaps even more inefficient:

diag(x[i[, 1], i[, 2]])

The perfect answer is x[i], both elegant and efficient. I learned this from another person’s answer to the same question. Then I looked at the help page ?`[`, and realized it was well-documented:

When indexing arrays by [ a single argument i can be a matrix with as many columns as there are dimensions of x; the result is then a vector with elements corresponding to the sets of indices in each row of i.

The example I gave above was just a special case: x could be an array of more than two dimensions, and does not have to be a matrix (a matrix is a special case of an array).

R help pages have too much hidden power. You have to carefully unfold and read them.

The help page is really powerful