admin管理员组

文章数量:1410725

Say I have a 10 x 10 two dimensional matrix...

set.seed(1)

mat <- matrix(sample(1:10,size=100,replace = T), ncol = 10)

How would I access the column and row position of the 83rd element in this matrix? It's easy enough to extract the element itself...

mat[83]

But I need the column and row position.

Say I have a 10 x 10 two dimensional matrix...

set.seed(1)

mat <- matrix(sample(1:10,size=100,replace = T), ncol = 10)

How would I access the column and row position of the 83rd element in this matrix? It's easy enough to extract the element itself...

mat[83]

But I need the column and row position.

Share Improve this question edited Mar 6 at 8:54 ThomasIsCoding 104k9 gold badges37 silver badges103 bronze badges asked Mar 5 at 20:28 llewmillsllewmills 3,6127 gold badges36 silver badges80 bronze badges 0
Add a comment  | 

2 Answers 2

Reset to default 4

You can use arranyInd with dim(mat):

arrayInd(83, .dim = dim(mat))

#      [,1] [,2]
# [1,]    3    9

# check
all.equal(
  mat[arrayInd(83, .dim = dim(mat))],
  mat[83]
)
# [1] TRUE

Or for ease of reading, add useNames = TRUE:

arrayInd(83, .dim = dim(mat),
         useNames = TRUE)

#       row  col
# [1,]    3    9

For a little more detail, arrayInd is related to which (see ?arrayInd) except its explicitly used to convert linear indices into row/col positions. It will return a matrix.

Note, you can use a vector of indices:

inx <- c(83, 92)
arrayInd(inx, dim(mat))

#      [,1] [,2]
# [1,]    3    9
# [2,]    2   10

And when using a vector of desired positions, if you wanted to clean it up for ease of identifying, could rename rows/cols like this:

indx <- c(83, 92)
`rownames<-`(arrayInd(indx, .dim = dim(mat), useNames = TRUE), paste0("ix", indx))

#      row column
# ix83   3      9
# ix92   2     10

Here is a base R solution from scratch (less elegant as @jpsmith's arrayInd solution)

Option %% + %/%

You can use %% + %/% to get the coordinates of linear indices in a 2D matrix

nr <- nrow(mat)
p <- idx - 1
cbind(row = p %% nr, col = p %/% nr) + 1

and an example is

set.seed(0)
mat <- matrix(runif(40), ncol = 5)
idx <- sample(40, 10)

nr <- nrow(mat)
p <- idx - 1
cbind(row = p %% nr, col = p %/% nr) + 1

which gives

      row col
 [1,]   2   2
 [2,]   6   5
 [3,]   4   3
 [4,]   4   4
 [5,]   7   5
 [6,]   7   3
 [7,]   6   1
 [8,]   1   4
 [9,]   3   5
[10,]   8   3

Benchmark

Given the benchmarking template like below

bm <- function(N) {
    set.seed(0)

    k <- sqrt(N)
    mat <- matrix(runif(N), ncol = k)
    idx <- sample(N, k)

    f1 <- function(mat, idx) {
        nr <- nrow(mat)
        p <- idx - 1
        cbind(p %% nr, p %/% nr) + 1
    }

    f2 <- function(mat, idx) {
        arrayInd(idx, dim(mat))
    }

    microbenchmark(
        f1(mat, idx),
        f2(mat, idx),
        unit = "relative",
        check = "equivalent"
    )
}

you might find some interesting results

> bm(1e2)
Unit: relative
         expr      min   lq     mean   median       uq       max neval
 f1(mat, idx) 1.000000 1.00 1.000000 1.000000 1.000000 1.0000000   100
 f2(mat, idx) 1.428571 1.55 1.480087 1.547619 1.581395 0.9018568   100

> bm(1e4)
Unit: relative
         expr      min       lq     mean   median       uq      max neval
 f1(mat, idx) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000   100
 f2(mat, idx) 1.152174 1.149533 1.161101 1.146341 1.147727 2.375527   100

> bm(1e6)
Unit: relative
         expr      min       lq     mean   median       uq      max neval
 f1(mat, idx) 1.422222 1.428941 1.412617 1.391304 1.238722 2.183183   100
 f2(mat, idx) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000   100

本文标签: rGet column and row position of nth element in a matrixStack Overflow