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 = ".")))