I've spent most of my R time in the tidyverse, and am now trying to branch out into more matrix math – but I'm very unfamiliar.
Perhaps it its core, my question is "is apply
the 'right'/'most current'/'best' function for generically working with matrices and arrays?" Is there a standard arrays package, like dplyr for data frames? Or are there matrix- and array-oriented functions I should be aware of.
But let's get into it
Right now I have two matrices. I would like to multiply the two matrices, as in a dot product, but rather than summing the results of each vector multiplication, I want to take the max. When multiplying a 5x5 matrix by a 5x2 matrix, this should result in a 5x2 matrix.
I already have a very simple apply
solution for this, but I'm not sure it's taking the most advantage of R's vectorization.
B <- matrix(c(0,1,1,0,0,
1,0,0,1,0,
1,0,0,0,1,
0,1,0,0,1,
0,0,1,1,0),
ncol = 5, dimnames = list(letters[1:5], letters[1:5]))
M <- data.frame(v1 = c(32, 1, 0, 14, 3),
v2 = c( 2, 6, 4, 9, 7))
rownames(M) <- letters[1:5]
M <- as.matrix(M)
My apply
solution
So far, I've done using apply to break matrix B into individual rows, and multiple each by M. I then use matrixStats::colMaxs
to take the maximum values of the output.
apply(B, 1, \(i) colMaxs(i * M)) %>% t()
# v1 v2
# a 1 6
# b 32 9
# c 32 7
# d 3 7
# e 14 9
Alternately, I could have delayed taking the column maxes, first making a 3-dimensional array:
B %>%
apply(1, \(i) i * M) %>%
array(dim = c(5, 2, 5),
dimnames = list(rownames(M), colnames(M), rownames(M))) %>%
apply(3, colMaxs)
Is there a more proper way to create this array from matrices B and M?
I imagine there's also a version where I don't make matrices but leave everything as vectors, appropriately repeat each one, and then create an array at the end, but if so, surely there's a package to help this confusing dimension-tracking:
# This yields the wrong result
rep(as.vector(B), 2) * rep(as.vector(M), 5) %>%
array(dim = c(5, 2, 5)) %>%
apply(3, colMaxs)
Question
Is there a non-apply
way to multiply matrices, resulting in a 3-dimensional array, where each element is the product of an element-wise multiplication? Should I be looking for one, or is apply
the appropriate tool for the job?