Create a correlation matrix from the correlation vector in R

I want to create a correlation matrix taking into account the correlation vector, which is the upper (or lower) triangular matrix of the correlation matrix.

The goal is to transform this vector

enter image description here

to this correlation matrix with 1s on the diagonal.

enter image description here

Do you know if there is a matrix creation method defined by a triangle above the diagonal and to set the diagonal to 1?

+7
vector matrix r correlation
source share
4 answers

I don't know if you have an automatic way to do this, but expanding your comment:

myvec <- c(-.55, -.48, .66, .47, -.38, -.46) mempty <- matrix(0, nrow = 4, ncol = 4) mindex <- matrix(1:16, nrow = 4, ncol = 4) mempty[mindex[upper.tri(mindex)]] <- myvec mempty[lower.tri(mempty)] <- t(mempty)[lower.tri(t(mempty))] diag(mempty) <- 1 mempty # [,1] [,2] [,3] [,4] # [1,] 1.00 -0.55 -0.48 0.47 # [2,] -0.55 1.00 0.66 -0.38 # [3,] -0.48 0.66 1.00 -0.46 # [4,] 0.47 -0.38 -0.46 1.00 

The function is quickly hacked here. I hope all my math steps are correct!

 vec2symmat <- function(invec, diag = 1, byrow = TRUE) { Nrow <- ceiling(sqrt(2*length(invec))) if (!sqrt(length(invec)*2 + Nrow) %% 1 == 0) { stop("invec is wrong length to create a square symmetrical matrix") } mempty <- matrix(0, nrow = Nrow, ncol = Nrow) mindex <- matrix(sequence(Nrow^2), nrow = Nrow, ncol = Nrow, byrow = byrow) if (isTRUE(byrow)) { mempty[mindex[lower.tri(mindex)]] <- invec mempty[lower.tri(mempty)] <- t(mempty)[lower.tri(t(mempty))] } else { mempty[mindex[upper.tri(mindex)]] <- invec mempty[lower.tri(mempty)] <- t(mempty)[lower.tri(t(mempty))] } diag(mempty) <- diag mempty } 

Here it is a different value for the diagonal.

 vec2symmat(1:3, diag = NA) # [,1] [,2] [,3] # [1,] NA 1 2 # [2,] 1 NA 3 # [3,] 2 3 NA 

An error message appears here if you are trying to provide data that cannot create a square matrix.

 vec2symmat(1:4) # Error in vec2symmat(1:4) : # invec is wrong length to create a square symmetrical matrix 

And with the default settings.

 vec2symmat(1:10) # [,1] [,2] [,3] [,4] [,5] # [1,] 1 1 2 3 4 # [2,] 1 1 5 6 7 # [3,] 2 5 1 8 9 # [4,] 3 6 8 1 10 # [5,] 4 7 9 10 1 
+6
source share

You can convince R that your vector is a distance object, then use as.matrix to convert it:

 > myvec <- c(-.55, -.48, .66, .47, -.38, -.46) > class(myvec) <- 'dist' > attr(myvec,'Size') <- 4 > as.matrix(myvec) 1 2 3 4 1 0.00 -0.55 -0.48 0.66 2 -0.55 0.00 0.47 -0.38 3 -0.48 0.47 0.00 -0.46 4 0.66 -0.38 -0.46 0.00 

Or a response option from @AnandaMahto (similar to the internal elements used above):

 > myvec <- c(-.55, -.48, .66, .47, -.38, -.46) > mycor <- matrix(0,4,4) > mycor[ col(mycor) < row(mycor) ] <- myvec > mycor <- mycor + t(mycor) > diag(mycor) <- 1 > mycor [,1] [,2] [,3] [,4] [1,] 1.00 -0.55 -0.48 0.66 [2,] -0.55 1.00 0.47 -0.38 [3,] -0.48 0.47 1.00 -0.46 [4,] 0.66 -0.38 -0.46 1.00 
+5
source share

An answer with some helper functions that may be useful in other tasks:

 `lower.tri<-` <- function(x,value){ x[lower.tri(x)] <- value x } `upper.tri<-` <- function(x,value){ y <- t(x) lower.tri(y) <- value t(y) } vec2mat <- function(r){ n <- (1+sqrt(1+8*length(r)))/2 x <- diag(1,n) lower.tri(x) <- upper.tri(x) <- r x } 

EDIT: note that upper.tri<- is not obtained simply by replacing "lower" with "upper" in lower.tri<- . This would make the result asymmetrical.

Result:

 vec2mat(c(-0.55, -0.48, 0.66, 0.47, -0.38, -0.46)) [,1] [,2] [,3] [,4] [1,] 1.00 -0.55 -0.48 0.66 [2,] -0.55 1.00 0.47 -0.38 [3,] -0.48 0.47 1.00 -0.46 [4,] 0.66 -0.38 -0.46 1.00 
+3
source share

In any programming language, I think you just do it with a pair of nested loops for loops like this:

Given:

Vector R; // I will use parentheses R (3) to denote the third element. // (which is stored in memory cell R [2] in languages ​​with zero arrays) int N;

Matrix M = matrix (N, N); // new instance of your matrix object, or you can just use arrays.

 int i,j,k; k=1; for(i=1;i<N;i++) { M(i,i)=1; for(j=i+1,j<=N;j++) { M(i,j)=M(j,i)=R[k]; k=k+1; } } 

Here, I assumed that you know what N is, and that you have basic objects such as available vectors and matrices. (If not, this is a big problem with a pattern for writing your first "objects"). Complex data structures, such as vectors, matrices, complex numbers, and histograms, create ideal objects. The right approach to object-oriented programming for scientific work is that you use objects to teach your compiler to understand the high-level data types that you want to use in your real work ... Objects are used to create a custom programming language perfect for your type of work. Everything that is usually useful should be included in the object, as these objects will grow and develop in order to be your reusable code base.

Top-level code can be either a very powerful, easy to read, and clean application (since most of the detailed work is done in objects). Also, for fast and dirty coding, the top-level code is where you put all the fragile hacks. Because it is not intended to be reused.

Once you get something like this debugged, you simply create a matrix constructor that takes the correlation vector and N as arguments, and initializes the matrix for you.

Of course, if you use some kind of high-level graphical mathematical program that has strong opinions about what you can and cannot do with matrices and vectors, then you will need to multiply the vector by N matrices to generate each of the columnar vectors of a finite matrix. (or read the manual)

At least you will need to tell us what is called a mathematical program ... :)

0
source share

All Articles