2

I need to multiply one matrix with one conditional vector, to get a vector of solutions, based on another matrix.

# Matrix A
lsA <- c(1,1,0,1,1,2,1,0,1,2,1,1,0,0,1,1,0,0,0,1)
A <- matrix(lsA,4,5, byrow = T)

# Matrix B
ls <- c("10","11","01","10","01","00","11","01","11","10","10","11","00","12","12","02","22","02","03","11")
B <- matrix(ls,4,5, byrow = T)

a1 <- c(0.128, 0.130, 0.280, 0.500, 0.650)
a2 <- c(0.055, 0.120, 0.250, 0.430, 0.600)

M1 = A%*%a1
M2 = A%*%a2

M3 <- NULL
for(i in 1:nrow(A)){
  if(B[[i]]=='00' | B[[i]]=='01' | B[[i]]=='10' | B[[i]]=='11'){
    M3[[i]] <- colSums(A[,i]*a1[i]) 
  } else {
    M3[[i]] <- colSums(A[,i]*a2[i]) 
  }

The code for M3 is not working... So I want to have a vector as M1 or M2, but the elements of the matrix A should be multiplied by one or the other vector, based on the codes of B.

Any ideas?

ana_gg
  • 370
  • 1
  • 9

2 Answers2

4

The issue is A[, i] drops the dimensions and return a vector. We need drop = FALSE and as we are using colSums, the input object is without a dimensions here i.e. ?colSums

x- an array of two or more dimensions, containing numeric, complex, integer or logical values, or a numeric data frame. For .colSums() etc, a numeric, integer or logical matrix (or vector of length m * n).

for(i in 1:nrow(A)){
   if('00' %in% B[,i] | '01' %in% B[,i] | '10' %in% B[, i] | '11' %in% B[,i]){
    M3[[i]] <- colSums(A[,i, drop = FALSE]*a1[i]) 
  } else {
    M3[[i]] <- colSums(A[,i, drop = FALSE]*a2[i]) 
  }
}

-output

> M3
[[1]]
[1] 0.64

[[2]]
[1] 0.39

[[3]]
[1] 0

[[4]]
[1] 0.86
akrun
  • 874,273
  • 37
  • 540
  • 662
  • Thanks for the code. It works, but are you sure about the result? It is weird that the summation for row three is "0" when all the values in a1 and a2 are positives. – ana_gg Mar 15 '22 at 16:34
  • @ana_gg your `A[,3]` is all 0 i.e. `A[, 3]# [1] 0 0 0 0` multiplywing with 0 returns 0 – akrun Mar 15 '22 at 16:36
  • @ana_gg I assume that you are multiplying the corresponding columns with corresponding elements of vector – akrun Mar 15 '22 at 16:38
  • thanks, sure, then it is not doing what I need, if you look at M1 and M2, you will see that both have non-zero values in row 3. – ana_gg Mar 15 '22 at 16:40
  • @ana_gg you are looping over the sequence of rows of 'A', which is 1 to 4, whereas values of 'a1' and 'a2' are of length 5 – akrun Mar 15 '22 at 16:43
  • if I multiply a matrix of 4*5 with a vector of 5*1 I will have a vector of 4*1, that is what I need. Maybe the loop is far from what I need. – ana_gg Mar 15 '22 at 16:47
  • @ana_gg your code is simply `> sum(A[, 1] * a1[1]) [1] 0.64 > sum(A[, 2] * a1[2]) [1] 0.39 > sum(A[, 3] * a1[3]) [1] 0` i.e. first column of A with first element of a1, and so on, get the `sum` – akrun Mar 15 '22 at 16:48
  • 1
    @ana_gg you may need to loop over the column index i.e. `Reduce("+", lapply(1:5, \(i) A[, i, drop = FALSE] * a1[i]))` gives the same output as `%*%` – akrun Mar 15 '22 at 16:53
  • The idea is to do elementwise sum – akrun Mar 15 '22 at 16:59
  • 1
    @ana_gg one more issue i notice din your code is using `[[` to extract `matrix` `B`, shouldn't it be `B[,i]` because `B[[1]]`, `B[[2]]`, etc are just the single element of B – akrun Mar 15 '22 at 17:06
0

Here is the solution. Now the loop is iterating over every element both column and row-wise, so it is making the multiplication element by element:

 M3 <- matrix(,4,5)
 for(i in 1:nrow(A)){
   for (j in 1:ncol(A))
   if(B[i,j]=='00' | B[i,j]=='01' | B[i,j]=='10' | B[i,j]=='11'){
     M3[i,j] <- A[i,j]*a1[j] 
   } else {
     M3[i,j] <- A[i,j]*a2[j] 
   }
 }
 M3 = rowSums(M3); M3
ana_gg
  • 370
  • 1
  • 9
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 16 '22 at 00:05