2

I wonder whether there is a straight forward way to exchange any pair of columns of a matrix in R.

Say we want to exchange the first (i=1) and third (j=3) column in matrix

n=3
mat  <- matrix(1:(n^2),ncol=n)

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

The following always works, regardless of the size n of the matrix

i=1; j=3
mat2     <- mat[,i]
mat[,i]  <- mat[,j]
mat[,j]  <- mat2

whereas direct commands like cbind(mat[,3],mat[,2],mat[,1]) (suggested in earlier threads SO1 and SO2) are limited to a given n.

is there a more direct ways to exchange two columns i and j in a matrix of size n?

Community
  • 1
  • 1
tomka
  • 2,516
  • 7
  • 31
  • 45

1 Answers1

3

Column pivoting can be done with pivoting index. Suppose you have matrix mat with n columns, and you want to pivot columns i and j, you can do:

piv <- 1:n; piv[c(i,j)] <- as.integer(c(j,i))
mat <- mat[, piv]

The as.integer call is for memory efficiency. piv <- 1:n is an integer vector, if i and j are doubles, simply calling piv[c(i,j)] <- c(j,i) will cause piv be first copied into a vector of doubles then be updated.

Zheyuan Li
  • 71,365
  • 17
  • 180
  • 248
  • About the same code length but does not create second, potentially large matrix – tomka Sep 06 '16 at 10:03
  • 3
    This *will* create a copy of the whole matrix. `mat[, c(i, j)] <- mat[, c(j, i)]` could be better maybe. Also, not sure what you need `as.integer` on a 2 length vector – David Arenburg Sep 06 '16 at 10:06
  • 1
    Eitherway it will copy the whole thing. The only way I could think of avoid copies it work with a data.table, something like `library(data.table) ; mat <- as.data.table(matrix(1:(n^2),ncol=n)) ; setcolorder(mat, piv)` which maybe doesn't suit OPs needs – David Arenburg Sep 06 '16 at 10:16
  • @DavidArenburg I think you might be able to (at least partially) avoid the copy by using a sparse matrix. – Roland Sep 06 '16 at 10:21