Reputation: 251
Say I have a permutation vector (row permutation)
x <- c(1,2,3,4,7,8,5,6,9,10) # I exchanged 7 with 5 and 8 with 6.
Is there any function in R that can generate the corresponding permutation matrix from permutation vector? If so, please give me a example.
Upvotes: 1
Views: 3281
Reputation: 11150
This what one can simply do in base R (no packages).
Let's start to set some matrix to permute.
# Let us assume your nxn-matrix is
n <- 3
(M <- matrix(as.numeric(1:(n*n)), n))
# [,1] [,2] [,3]
#[1,] 1 4 7
#[2,] 2 5 8
#[3,] 3 6 9
For a single permutation matrix, based on a random vector permutation (pivot), we have:
## To generate the permutation matrix associated to a random 1:n permutation:
vperm <- sample(1:n)
(mperm <- Reduce(\(m,i) `[[<-`(m, i, vperm[i], 1), 1:n, matrix(0, n, n)))
# [,1] [,2] [,3]
#[1,] 0 1 0
#[2,] 1 0 0
#[3,] 0 0 1
## To permute the columns of M:
t(mperm) %*% M
# [,1] [,2] [,3]
#[1,] 2 5 8
#[2,] 1 4 7
#[3,] 3 6 9
## And, to permute the rows of M:
M %*% mperm
# [,1] [,2] [,3]
#[1,] 4 1 7
#[2,] 5 2 8
#[3,] 6 3 9
Now, we generate all possible pivot vectors and the related permutation matrices
## To generate all possible random 1:n permutations:
vdisps <- expand.grid(rep(list(1:n), n)) # with repetitions
vperms <- Filter(\(v) length(unique(t(v))) == n, split(vdisps, 1:n^n))
## To generate the permutation matrices associated to each random permutation:
mperms <- lapply(vperms, \(permdf)
Reduce(\(m,i) `[[<-`(m, i, permdf[[i]], 1), 1:n, matrix(0, n, n)))
## The related list of column-permutated matrices are
lapply(mperms, \(P) t(P) %*% M)
Of course, this is R, so we can use its subsetting features.
## Given
oo <- order(vperm) #,
## we can replace t(mperm) %*% M with:
identical(t(mperm) %*% M, M[oo, ]) # TRUE
identical(M %*% mperm, M[, oo]) # TRUE
This is what is suggested to do when using the Cholesky decomposition with chol(..., pivot = TRUE)
.
NB as.numeric()
is important, when generating M
, to have identical()
to work.
Upvotes: 0
Reputation: 887901
This could also be done with sparseMatrix
library(Matrix)
m1 <- sparseMatrix(seq_along(v1), v1, x=1)
We can coerce it to matrix
with as.matrix
as.matrix(m1)
v1 <- c(1,2,3,4,7,8,5,6,9,10)
Upvotes: 3
Reputation: 44340
I believe this can be done by reordering the rows of the identity matrix:
x <- c(1,2,3,4,7,8,5,6,9,10)
diag(length(x))[x,]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 1 0 0 0 0 0 0 0 0 0
# [2,] 0 1 0 0 0 0 0 0 0 0
# [3,] 0 0 1 0 0 0 0 0 0 0
# [4,] 0 0 0 1 0 0 0 0 0 0
# [5,] 0 0 0 0 0 0 1 0 0 0
# [6,] 0 0 0 0 0 0 0 1 0 0
# [7,] 0 0 0 0 1 0 0 0 0 0
# [8,] 0 0 0 0 0 1 0 0 0 0
# [9,] 0 0 0 0 0 0 0 0 1 0
# [10,] 0 0 0 0 0 0 0 0 0 1
Upvotes: 3