Varren Varren - 17 days ago 5
R Question

Multiply a matrix' columns by its columns

I have a 4x100 matrix where I would like to multiply column 1 with row 1 in its transpose etc and store these matrices somewhere to be able to take the sum of these new matrices lateron.

I really don't know where to start due to the fact that I get 4x4 matrices after the column-row-multiplication. Due to this fact I cannot store them in a matrix

data:

mm num[1:4,1:100]

mm_t num[1:100,1:4]


I'm thinking of creating a list in some way

list1=list()
for(i in 1:100){
list1[i] <- mm[,i]%*%mm_t[i,]
}


but I need some more indices i think because this just leaves me with a number in each argument..

Answer

Let's start with some sample data. Please get in the habit of including things like this in your question:

nr = 4
nc = 100
set.seed(47)
mm = matrix(runif(nr * nc), nrow = nr)

Here's a working answer, very similar to your attempt:

result = list()
for (i in 1:ncol(mm)) result[[i]] = mm[, i] %*% t(mm[, i])
result[1:2]
# [[1]]
#           [,1]      [,2]      [,3]      [,4]
# [1,] 0.9544547 0.3653018 0.7439585 0.8035430
# [2,] 0.3653018 0.1398132 0.2847378 0.3075428
# [3,] 0.7439585 0.2847378 0.5798853 0.6263290
# [4,] 0.8035430 0.3075428 0.6263290 0.6764924
# 
# [[2]]
#           [,1]      [,2]      [,3]      [,4]
# [1,] 0.3289532 0.3965557 0.2231443 0.2689613
# [2,] 0.3965557 0.4780511 0.2690022 0.3242351
# [3,] 0.2231443 0.2690022 0.1513691 0.1824490
# [4,] 0.2689613 0.3242351 0.1824490 0.2199103

As to why yours didn't work, we can experiment and see that indeed we get a number rather than a matrix. The reason is that when you subset a single row or column of a matrix, the dimensions are "dropped" and it is coerced to a plain vector. And when you matrix multiply two vectors, you get their dot product.

mmt = t(mm)
mm[, 1] %*% mmt[1, ]
#          [,1]
# [1,] 2.350646
dim(mm[, 1])
# NULL
dim(mmt[1, ])
# NULL

We can avoid this by specifying drop = FALSE in the subset code

dim(mmt[1, , drop = FALSE])
# [1] 1 4

And thus slightly modify your attempt, just adding drop = FALSE will make it work.

res2 = list()
for (i in 1:ncol(mm)) res2[[i]] = mm[, i] %*% mmt[i, , drop = FALSE]
identical(result, res2)
# [1] TRUE
Comments