lowndrul
lowndrul

Reputation: 3815

More general or efficient approach for this matrix multiplication?

In R, is there a more efficient and/or general way to produce the desired output from the two matrices below? I'm suspicious that what I've done is just some esoteric matrix multiplication operation of which I'm not aware.

ff <- matrix(1:6,ncol=2)
# [,1] [,2]
# [1,]    1    4
# [2,]    2    5
# [3,]    3    6

bb <- matrix(7:10,ncol=2)
# [,1] [,2]
# [1,]    7    9
# [2,]    8   10

# DESIRE:
#  7 36
# 14 45
# 21 54
#  8 40
# 16 50
# 24 60

This works, but isn't the general solution I'm looking for:

rr1 <- t(t(ff) * bb[1,])
rr2 <- t(t(ff) * bb[2,])
rbind(rr1,rr2)
# [,1] [,2]
# [1,]    7   36
# [2,]   14   45
# [3,]   21   54
# [4,]    8   40
# [5,]   16   50
# [6,]   24   60

This next code block seems pretty efficient and is general. But is there a better way? Something like kronecker(ffa,bba)? (which clearly doesn't work in this case)

ffa <- matrix(rep(t(ff),2), ncol=2, byrow=T)
bba <- matrix(rep(bb,each=3), ncol=2)
ffa * bba
# [,1] [,2]
# [1,]    7   36
# [2,]   14   45
# [3,]   21   54
# [4,]    8   40
# [5,]   16   50
# [6,]   24   60

This is related to my other questions:

  1. Using apply function over the row margin with expectation of stacked results, where I'm trying to understand the behavior of apply itself and:

  2. Is this an example of some more general matrix product?, where I'm asking about the theoretical math, specifically.

Upvotes: 1

Views: 135

Answers (2)

&#216;yvind Langsrud
&#216;yvind Langsrud

Reputation: 181

The functionality you are seeking for is available within the Matrix package as the function KhatriRao. Since the function is in Matrix, output is a matrix of class "dgCMatrix" (sparse matrix). You can transform it to an ordinary matrix of class "matrix" by as.matrix.

library(Matrix)
as.matrix(KhatriRao(bb, ff))

Upvotes: 3

G. Grothendieck
G. Grothendieck

Reputation: 269694

Use a kronecker product and pick off the appropriate columns:

kronecker(bb, ff)[, c(diag(ncol(bb))) == 1]

or using the infix operator for kronecker:

(bb %x% ff)[, c(diag(ncol(bb))) == 1]

Another approach is to convert the arguments to data frames and mapply kronecker across them. For the case in the question this performs the calculation cbind(bb[, 1] %x% ff[, 1], bb[, 2] %x% ff[, 2]) but in a more general manner without resorting to indices:

mapply(kronecker, as.data.frame(bb), as.data.frame(ff))

or using the infix operator for kronecker:

mapply(`%x%`, as.data.frame(bb), as.data.frame(ff))

Upvotes: 3

Related Questions