0

Suppose I have a list like this in R:

> L
[[1]]
[1] 0.6876619 0.7847888 0.6377801 0.2078056 0.8981001

[[2]]
[1] 0.9358160 0.8905056 0.7715877 0.8648426 0.4915060

[[3]]
[1] 0.88095630 0.08010288 0.15140700 0.35400865 0.60317717

[[4]]
[1] 0.07436267 0.85873209 0.49881141 0.92363954 0.87208334

And I want to find the correlation coefficient between each pair of vectors, e.g, cor(L[[i]],L[[j]]). Is there any solution to perform it with the apply family function? Please take it as a specific case of a general question: What if we need to do a triple nested loop over a List() in R?

3 Answers 3

2

You can nest lapply calls:

lapply(L, function(x) lapply(L, function(y) cor(x,y))))

If you want the results presented more nicely, put them in a matrix:

    L <- list(rnorm(10), rnorm(10), rnorm(10))
    matrix(unlist(lapply(L, 
                         function(x) lapply(L, 
                                            function(y) cor(x,y)))),
           length(L))
#>            [,1]       [,2]       [,3]
#> [1,]  1.0000000 -0.3880931 -0.4164212
#> [2,] -0.3880931  1.0000000  0.4158335
#> [3,] -0.4164212  0.4158335  1.0000000

Created on 2021-05-31 by the reprex package (v2.0.0)

Sign up to request clarification or add additional context in comments.

Comments

2

You could use mapply. Generate all the combinations of interest (pairs, triples, ...) and then apply

L=replicate(5,rnorm(5),simplify=F)

tmp=expand.grid(1:length(L),1:length(L))

tmp$cor=mapply(
  function(y,x){cor(L[[y]],L[[x]])},
  tmp$Var1,
  tmp$Var2
)

   Var1 Var2        cor
1     1    1  1.0000000
2     2    1  0.1226881
3     3    1 -0.2871613
4     4    1  0.4746545
5     5    1  0.9779644
6     1    2  0.1226881
7     2    2  1.0000000
...

Comments

2

You can cbind the list and call cor with the resulting matirx.

cor(do.call(cbind, L))
#           [,1]        [,2]        [,3]        [,4]
#[1,]  1.0000000 -0.46988357  0.14151672  0.14151672
#[2,] -0.4698836  1.00000000 -0.09177819 -0.09177819
#[3,]  0.1415167 -0.09177819  1.00000000  1.00000000
#[4,]  0.1415167 -0.09177819  1.00000000  1.00000000

In case there is one more level in the list use unlist.

L2 <- lapply(L, list) #Create list with one more level.
cor(do.call(cbind, unlist(L2, FALSE)))

In case it is unknown or mixed, a recursive call of a function could be used:

L3 <- list(L[[1]], L[[2]], L2[[3]], L2[[4]])
f <- function(x) {
  if(is.list(x)) sapply(x, f)
  else x
}
cor(f(L3))

Data:

L <- list(c(0.6876619,0.7847888,0.6377801,0.2078056,0.8981001)
        , c(0.9358160,0.8905056,0.7715877,0.8648426,0.4915060)
        , c(0.88095630,0.08010288,0.15140700,0.35400865,0.60317717)
        , c(0.88095630,0.08010288,0.15140700,0.35400865,0.60317717))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.