0
votes

This question is similar to the one I asked previously, but I define the groups here slightly differently.

I am trying to multiply certain elements inside a vector with a matrix, while setting all other elements within the vector to zero, and then repeat the process for the next group. The elements I want to use are n elements apart.

My dataset is again very large, so for illustrative purposes let:

a <- c(2:7)
b <- matrix(1:36, byrow = TRUE, nrow = 6)
description <- c("AA1", "AA2", "AA3", "BB1", "BB2", "BB3")
names(a) <- description

giving:

a

AA1 AA2 AA3 BB1 BB2 BB3 
  2   3   4   5   6   7 

b
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    2    3    4    5    6
[2,]    7    8    9   10   11   12
[3,]   13   14   15   16   17   18
[4,]   19   20   21   22   23   24
[5,]   25   26   27   28   29   30
[6,]   31   32   33   34   35   36

Define a as having three groups:

  • element 1 and 4 for group 1
  • element 2 and 5 for group 2
  • element 3 and 6 for group 3

So in this example I want to match every element with the same number in the vector and then multiply this with the matrix. So for group 1 the vector would be (2, 0, 0, 5, 0, 0) group 2 (0, 3, 0, 0, 6, 0) and group 3 (0, 0, 4, 0, 0, 7)

The vector matrix multiplication (a %*% b) for group 1 would give results:

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]   97  104  111  118  125  132

So I was thinking of either matching the numbers inside the vector using the grepl code, or somehow tell r to set the two elements between the groups to zero, and then repeat the process for the next group.

What would be the best code for this?

1

1 Answers

1
votes

g is the grouping vector c(1, 2, 3, 1, 2, 3) such that all elements corresponding to the same value of the grouping vector belong to the same group. Now outer(...) gives a three column matrix Ind, each of whose columns is an indicator variable for one group. For each column of Ind perform the indicated calculation in the sapply:

g <- as.numeric(gsub("\\D", "", names(a)))
Ind <- outer(g, unique(g), `==`)
sapply(1:ncol(Ind), function(i) a %*% (b * Ind[, i]))

giving:

     [,1] [,2] [,3]
[1,]   97  171  269
[2,]  104  180  280
[3,]  111  189  291
[4,]  118  198  302
[5,]  125  207  313
[6,]  132  216  324

The last line of code could alternately be written:

sapply(split(Ind, col(Ind)), function(ind) a[ind] %*% b[ind, ])

or

sapply(1:ncol(Ind), function(i) a %*% diag(Ind[, i]) %*% b)

Update: Have revised based on clarification of the question.