简体   繁体   中英

How to calculate correlation between matrices with different column dimention in R

I have two matrices with same number of rows and different number of columns as:

mat1 <- matrix(rnorm(20), 4, 5)
mat2 <- matrix(rnorm(12), 4, 3)

Since i have the same number of rows I want to calculate the following correlation between the columns of the matrices:

 cor.test(mat1[,1], mat2[,1])
 cor.test(mat1[,1], mat2[,2])
 cor.test(mat1[,1], mat2[,3])
 cor.test(mat1[,2], mat2[,1])
 cor.test(mat1[,2], mat2[,2])
 cor.test(mat1[,2], mat2[,3])
 ...........
 ...........
 cor.test(mat1[,5], mat2[,3])

for(i in 1:5){
  for(j in 1:3){
    pv[i,j] <- cor.test(mat1[, i], mat2[ , j])$p.value
  }
}

At the end I want a matrix(5 * 3) or vector containing the correlation values, can anyone help?

Can i use this to return both p.value and estimate?

 FUN <- function(x, y) { 
    res <- cor.test(x, y, method="spearman", exact=F) 
    return(list(c = res$estimate, p = res$p.value)) 
  }

 r1 <- outer(colnames(mat1), colnames(mat2), Vectorize(function(i,j) FUN(mat1[,i], mat2[,j])$p))
 r2 <- outer(colnames(mat1), colnames(mat2), Vectorize(function(i,j) FUN(mat1[,i], mat2[,j])$c))

Thank you.

Why don't you just use cor function to calculate the pearson correlation?

seed(1)
mat1 <- matrix(rnorm(20), 4, 5)
mat2 <- matrix(rnorm(12), 4, 3)
cor(mat1, mat2)
       [,1]        [,2]        [,3]
[1,]  0.4406765 -0.70959590  0.10731768
[2,] -0.2566199 -0.01588993 -0.63630159
[3,] -0.9813313  0.85082165 -0.77172317
[4,]  0.6121358 -0.38564314  0.87077092
[5,] -0.6897573  0.66272015 -0.08380553

To double check,

> col_1 <- 3
> col_2 <- 2
# all.equal is used to compare numeric equality where `==` is discouraged
> all.equal(cor(mat1, mat2)[col_1, col_2], cor(mat1[,col_1], mat2[,col_2]))
[1] TRUE

They are equal!

An alternative, slightly easier to understand than loops in my opinion:

sapply(
  data.frame(mat1),
  function(x) Map(function(a,b) cor.test(a,b)$p.value,
                                list(x),
                                as.data.frame(mat2))
)

Result:

#     X1        X2        X3        X4        X5       
#[1,] 0.7400541 0.8000358 0.5084979 0.4441933 0.9104712
#[2,] 0.2918163 0.2764817 0.956807  0.6072979 0.4395218
#[3,] 0.2866105 0.4095909 0.5648188 0.1746428 0.9125866

I think all you need is to define your matrix first

mat_cor <- matrix(nrow=ncol(mat1), ncol=ncol(mat2))
for(i in 1:5)
    {
        for(j in 1:3)
            {
                mat_cor[i,j] <- cor.test(mat1[, i], mat2[ , j])$p.value
            }
    }

Output

mat_cor

          [,1]      [,2]        [,3]
[1,] 0.9455569 0.8362242 0.162569342
[2,] 0.7755360 0.9849619 0.775006329
[3,] 0.8799139 0.8050564 0.001358697
[4,] 0.1574388 0.1808167 0.618624825
[5,] 0.8571844 0.8897125 0.879818822

I supose you would like to do it without for's. With base stuff, here is the double apply aproach:

apply(mat1, 2, function(col_mat1){
  apply(mat2, 2, function(col2, col1) {
    cor.test(col2, col1)$p.value
  }, col1=col_mat1)
})

The outter apply iterates at mat1 columns and serves one side of cor.test() . The inner one does the same, but now fills the second side of cor.test() . In practie, apply is replacing the for's.

You can try with something like this

pv <- c()
for(i in 1:dim(mat1)[2]){
  for(j in 1:dim(mat2)[2]){
    pv <-c(c, cor.test(mat1[, i], mat2[ , j])$estimate)
  }
}

dim(pv) <- c(dim(mat1)[2], dim(mat2)[2])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM