Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient way to create a circulant matrix in R

I want to create a circulant matrix from a vector in R. A circulant matrix is a matrix with the following form.

1 2 3 4
4 1 2 3
3 4 1 2
2 3 4 1

The second row is the same as the first row except the last element is at the beginning, and so on.

Now I have the vector, say, (1, 2, 3, 4) and I want to find a efficient (fast) way to create this matrix. In practice, the numbers are not integers and can be any numbers.

Here is what I am doing now.

x <- 1:4
n <- length(x)
mat <- matrix(NA, n, n)
for (i in 1:n) {
    mat[i, ] <- c(x[-(1:(n+1-i))], x[1:(n+1-i)])
}

I wonder if there is a faster way to do this? I need to generate this kind of matrices over and over. A small improvement for one step will make a big difference. Thank you.

like image 654
JACKY Li Avatar asked Apr 03 '13 18:04

JACKY Li


1 Answers

This makes use of vector recycling (it throws a warning):

circ<-function(x) { 
    n<-length(x)
    matrix(x[matrix(1:n,n+1,n+1,byrow=T)[c(1,n:2),1:n]],n,n)
}
circ(letters[1:4])
#     [,1] [,2] [,3] [,4]
#[1,] "a"  "b"  "c"  "d" 
#[2,] "d"  "a"  "b"  "c" 
#[3,] "c"  "d"  "a"  "b" 
#[4,] "b"  "c"  "d"  "a" 
like image 56
ndoogan Avatar answered Oct 28 '22 18:10

ndoogan