Say we want to get a square matrix into a vector. We can do:

to.upper<-function(X) X[upper.tri(X,diag=TRUE)]

but this will give us our upper triangular matrix as a vector *by column*, i.e.:

> X

[,1] [,2] [,3] [,4] [,5]

[1,] -0.329 -0.825 -0.906 0.834 0.702

[2,] 1.195 -0.237 -1.132 -0.827 0.150

[3,] -0.097 -1.270 -1.397 0.450 0.791

[4,] 0.883 -0.574 1.538 -2.632 0.135

[5,] 1.993 -0.520 -0.071 0.094 -0.064

> to.upper(X)

[1] -0.329 -0.825 -0.237 -0.906 -1.132 -1.397 0.834 -0.827 0.450 -2.632 0.702 0.150 0.791 0.135 -0.064

[,1] [,2] [,3] [,4] [,5]

[1,] -0.329 -0.825 -0.906 0.834 0.702

[2,] 1.195 -0.237 -1.132 -0.827 0.150

[3,] -0.097 -1.270 -1.397 0.450 0.791

[4,] 0.883 -0.574 1.538 -2.632 0.135

[5,] 1.993 -0.520 -0.071 0.094 -0.064

> to.upper(X)

[1] -0.329 -0.825 -0.237 -0.906 -1.132 -1.397 0.834 -0.827 0.450 -2.632 0.702 0.150 0.791 0.135 -0.064

If we want to get our upper triangular matrix as a vector *by row* (as I did), we can use:

to.upper<-function(X) t(X)[lower.tri(X,diag=TRUE)]

which works just as we'd hoped, i.e.:
> X

[,1] [,2] [,3] [,4] [,5]

[1,] -0.329 -0.825 -0.906 0.834 0.702

[2,] 1.195 -0.237 -1.132 -0.827 0.150

[3,] -0.097 -1.270 -1.397 0.450 0.791

[4,] 0.883 -0.574 1.538 -2.632 0.135

[5,] 1.993 -0.520 -0.071 0.094 -0.064

> to.upper(X)

[1] -0.329 -0.825 -0.906 0.834 0.702 -0.237 -1.132 -0.827 0.150 -1.397 0.450 0.791 -2.632 0.135 -0.064

[,1] [,2] [,3] [,4] [,5]

[1,] -0.329 -0.825 -0.906 0.834 0.702

[2,] 1.195 -0.237 -1.132 -0.827 0.150

[3,] -0.097 -1.270 -1.397 0.450 0.791

[4,] 0.883 -0.574 1.538 -2.632 0.135

[5,] 1.993 -0.520 -0.071 0.094 -0.064

> to.upper(X)

[1] -0.329 -0.825 -0.906 0.834 0.702 -0.237 -1.132 -0.827 0.150 -1.397 0.450 0.791 -2.632 0.135 -0.064

(Note that if we have a symmetric matrix than the upper triangular matrix by row & the lower triangular matrix by column are the same. Here I used a non-symmetric square matrix so that we could tell these apart.)

Similarly, here's a function that puts a vector into the upper diagonal of a matrix - by row:

ReplyDeleteupper.diag<-function(x){

m<-(-1+sqrt(1+8*length(x)))/2

X<-lower.tri(matrix(NA,m,m),diag=TRUE)

X[X==TRUE]<-x

t(X)

}

Hi

DeleteCould you please explain why m<-(-1+sqrt(1+8*length(x)))/2

thanks

Hmmm. This is a very old post. Must be the solution for the number of elements in the upper diagonal of a square matrix of dimension m x m. In particular, x=m*(m-1)/2 solved for m.

DeleteThank you so much for you post! I just need this!!!

ReplyDelete