3
votes

Given two matrices with the same number of columns.

m1 <- matrix(1:12, ncol=3)
m2 <- matrix(10:2, ncol=3)

Say I have a function that takes two vectors and do something like the product of each vectors min (toy example):

fun <- function(v1, v2)(min(v1)*min(v2))

I can't get my head around how to do the function on all combinations of columns by using two nested apply calls. To use apply on m1 versus first column is like:

apply(m1, 2, fun, m2[,1])

Im stuck with looping through all m2's columns like:

m3<-matrix(NA, ncol=3, nrow=3)
for(c in 1:ncol(m2)){ 
m3[,c] <- apply(m1, 2, fun, m2[,c])
}

This gives

> m3
     [,1] [,2] [,3]
[1,]   10    9    8
[2,]   50   45   40
[3,]   90   81   72

So how to frame this loop as an apply ?

EDIT: the code had an error - sorry. See edit

3

3 Answers

3
votes

If you are interested using nested apply, we can try

apply(m1, 2, function(x) apply(m2, 2, function(y) min(x) * min(y)))

#     [,1] [,2] [,3]
#[1,]    8   40   72
#[2,]    5   25   45
#[3,]    2   10   18

As you already have the function defined,

apply(m1, 2, function(x) apply(m2, 2, fun, x))

would be simpler.

2
votes

I would use mapply here, and change the function slightly so it passes indices rather than the actual columns:

m1 <- matrix(1:12, ncol=3)
m2 <- matrix(10:2, ncol=3)

fun <- function(i1, i2) (min(m1[,i1])*min(m2[,i2]))

res <- matrix(mapply(fun, rep(1:3, times=3), rep(1:3, each=3)), ncol=3)

Does this do what you want?

0
votes

We can do this easier with vectorized functions such as outer colMins (from matrixStats)

library(matrixStats)
outer(colMins(m1), colMins(m2))
#    [,1] [,2] [,3]
#[1,]    8    5    2
#[2,]   40   25   10
#[3,]   72   45   18