Home > Net >  Loop for constrained matrix calculation
Loop for constrained matrix calculation

Time:03-05

I have a random matrix in R, namely M1 defined as follows

M1<-matrix(1:20,nrow=4,ncol=5)

> M1
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20

and I want to create a second one based on the following constrain. Each row must contain the row summation minus the previous point. Meaning element (1,1) = 45, (1,2)=44, (1,3)=39, etc. for each row. But I want to make it in a loop so every time someone changes the matrix (and it's dimension) the code to be able to calculate the corresponding matrix. The final matrix, called M2 must be of that form

> M2
     [,1] [,2] [,3] [,4] [,5]
[1,]   45   44   39   30   17
[2,]   50   48   42   32   18
[3,]   55   52   45   34   19
[4,]   60   56   48   36   20 

How can I define the loop in order to calculate it?

CodePudding user response:

There is rowCumsums function in matrixStats which can be used

library(matrixStats)
ind <- ncol(M1):1
rowCumsums(M1[, ind])[, ind]

-output

     [,1] [,2] [,3] [,4] [,5]
[1,]   45   44   39   30   17
[2,]   50   48   42   32   18
[3,]   55   52   45   34   19
[4,]   60   56   48   36   20

Or may use revcumsum from spatstat.utils

library(spatstat.utils)
t(apply(M1, 1, revcumsum))

-output

      [,1] [,2] [,3] [,4] [,5]
[1,]   45   44   39   30   17
[2,]   50   48   42   32   18
[3,]   55   52   45   34   19
[4,]   60   56   48   36   20

CodePudding user response:

Some base R options

> rowSums(M1) - cbind(0, do.call(cbind, Reduce(` `, as.data.frame(M1)[-ncol(M1)], accumulate = TRUE)))
     [,1] [,2] [,3] [,4] [,5]
[1,]   45   44   39   30   17
[2,]   50   48   42   32   18
[3,]   55   52   45   34   19
[4,]   60   56   48   36   20

or

> t(apply(M1, 1, function(v) sum(v) - head(cumsum(c(0, v)), -1)))
     [,1] [,2] [,3] [,4] [,5]
[1,]   45   44   39   30   17
[2,]   50   48   42   32   18
[3,]   55   52   45   34   19
[4,]   60   56   48   36   20
  • Related