Home > database >  Operations between list objects in R with apply function
Operations between list objects in R with apply function

Time:01-18

I have a 1x5 matrix A and a list of 5 B with matrices (double [100x100]) in R. Each argument of A corresponds to one B and I want to create the following function

C = ( max(A[,i],A[,j]) * B[[i]] * B[[j]] ) / 2

for example to calculate C between 1 and 2 I can use the following

set.seed(123)
A <- matrix(c(5.2,6.9,32,40,8.3), ncol = 5 )

B <- list(matrix(rnorm(100 * 100, mean = 0, sd = 1), 100, 100), 
          matrix(rnorm(100 * 100, mean = 0, sd = 1), 100, 100), 
          matrix(rnorm(100 * 100, mean = 0, sd = 1), 100, 100), 
          matrix(rnorm(100 * 100, mean = 0, sd = 1), 100, 100), 
          matrix(rnorm(100 * 100, mean = 0, sd = 1), 100, 100))

C_1.2<- max(A[,1],A[,2]) * (unlist(B[[1]])*unlist(B[[2]]))

I want to create a list in R that does the above for all possible combinations with the use of an apply function? I want the names to be C_j.j. I manage to it as follows:

combinations <- combn(1:5, 2)

result_list <- lapply(1:ncol(combinations), function(i){
  j <- combinations[1, i]
  k <- combinations[2, i]
  
  C <- (max(A[, j], A[, k]) * B[[j]] * B[[k]]) / 2
  
  list(C)
})

names(result_list) <- paste0("C_", combinations[1, ], ".", combinations[2, ])

However I can't produce the C_1.1, C_2.2,C_3.3,C_4.4,C_5.5. How can I fix that? I am thinking when i=j, then to calculate C_i.i <- (A[,i] * B[[i]]^2) / 2 .

A solution based on the answers is

out2 <- apply(expand.grid(seq_along(B), seq_along(B)), 1, \(i) 
              (max(A[, i]) * (B[[i[1]]] * B[[i[2]]])), simplify = FALSE)
names(out2) <- paste0("C_", do.call(paste, 
                                    c(expand.grid(seq_along(B), seq_along(B)), sep = ".")))

or

C <- lapply(1:5, function(i) {
  lapply(1:5, function(j) {
    if (i == j) {
      C_i.i <- (A[,i] * B[[i]]^2)
    } else {
      C_i.j <- max(A[,i],A[,j]) * (unlist(B[[i]])*unlist(B[[j]]))
    }
  })
})

which however creates all possible scenarios and doubles the computational time since we know that C_1.2 = C_2.1 and ton calculation is needed.

CodePudding user response:

We may do this directly in combn

out <- combn(seq_along(B), 2, FUN = function(i) 
    (max(A[, i]) * (B[[i[1]]] * B[[i[2]]])), simplify = FALSE)
names(out) <- paste0("C_", combn(seq_along(B), 2, FUN = paste, collapse = "."))

-checking the output with OP's output

> C_1.2<- max(A[,1],A[,2]) * (unlist(B[[1]])*unlist(B[[2]]))
> all.equal(out[[1]], C_1.2)
[1] TRUE

If we want all combinations, use expand.grid

out2 <- apply(expand.grid(seq_along(B), seq_along(B)), 1, \(i) 
    (max(A[, i]) * (B[[i[1]]] * B[[i[2]]])), simplify = FALSE)
names(out2) <- paste0("C_", do.call(paste, 
    c(expand.grid(seq_along(B), seq_along(B)), sep = ".")))
  • Related