Getting a 3d array from two 2d arrays

How can I get one 3d array from two 2d arrays?

So, given A and B:

(A <- matrix(1:6, nrow = 3, ncol = 2, dimnames = list(c("A", "B", "C"), c("D", "E"))))
  D E
A 1 4
B 2 5
C 3 6
(B <- matrix(1:8, nrow = 4, ncol = 2, dimnames = list(c("F", "G", "H", "I"), c("D", "E"))))
  D E
F 1 5
G 2 6
H 3 7
I 4 8

I want to get a new 3d array containing the outer products of the column vectors. Here is a hardcoded example of expected result:

(outer(A[,"D"], B[,"D"]))
  F G H  I
A 1 2 3  4
B 2 4 6  8
C 3 6 9 12
(outer(A[,"E"], B[,"E"]))
   F  G  H  I
A 20 24 28 32
B 25 30 35 40
C 30 36 42 48

I can do a code-it-up, but there must be a functional approach to solve this?

Hi,

I guess this is not really what you want as it is still coded up, but it's the 'cleanest' I can get

A <- matrix(1:6, nrow = 3, ncol = 2, 
            dimnames = list(c("A", "B", "C"), c("D", "E")))
B <- matrix(1:8, nrow = 4, ncol = 2, 
            dimnames = list(c("F", "G", "H", "I"), c("D", "E")))

C = sapply(1:ncol(A), function(i){
  outer(A[,i], B[,i])
}, simplify = F)

array(c(C[[1]], C[[2]]), dim = c(dim(C[[1]]),2), 
          dimnames = dimnames(C[[1]]))
#> , , 1
#> 
#>   F G H  I
#> A 1 2 3  4
#> B 2 4 6  8
#> C 3 6 9 12
#> 
#> , , 2
#> 
#>    F  G  H  I
#> A 20 24 28 32
#> B 25 30 35 40
#> C 30 36 42 48

Created on 2023-01-13 by the reprex package (v2.0.1)

PJ

1 Like

Thanks for input - I was sort of along the same lines, but was merely wondering if some nice vectorised function, which I was unaware of, would do the trick, alas... So for future reference this is what I converged at:

outer_col_prod <- function(X, Y){
  outer_prod_list <- lapply(
    X = 1:ncol(X),
    FUN = function(j){
      return( outer(X[,j], Y[,j]) ) })
  return(
    as.table(
      x = array(
        data = unlist(outer_prod_list),
        dim = c(nrow(X), nrow(Y), ncol(X)),
        dimnames = list(
          X = rownames(X),
          Y = rownames(Y),
          Z = colnames(X))))
  )
}
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.