Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculate row-wise matrix cumsum from vector

Tags:

r

matrix

Given a vector I would like to create a square matrix where elements of vector are on diagonal and there is row-wise cumsum of elements.

Example vector:

vec <- c(1, 2, 3, 4)

Required output:

     [,1] [,2] [,3] [,4]
[1,]    1    3    6   10
[2,]    0    2    5    9
[3,]    0    0    3    7
[4,]    0    0    0    4

Now, I am using double for loop function:

diagSum <- function(vec) {
  mat <- diag(vec)
  for (i in seq(nrow(mat))) {
    for (j in seq(i, ncol(mat))) {
      if (j > i) {
        mat[i, j] <- mat[i, j - 1] + mat[j, j]      
      }
    }
  }
  mat
}

What would be R-way (avoiding for loops) of doing this?

like image 634
Tomas Greif Avatar asked Jan 27 '15 11:01

Tomas Greif


3 Answers

m <- matrix(vec, nrow = length(vec), ncol = length(vec), byrow =TRUE)
m[lower.tri(m)] <- 0
t(apply(m, 1, cumsum))
#     [,1] [,2] [,3] [,4]
#[1,]    1    3    6   10
#[2,]    0    2    5    9
#[3,]    0    0    3    7
#[4,]    0    0    0    4
like image 200
Roland Avatar answered Oct 10 '22 18:10

Roland


One way to do it:

x <- c(1, 2, 3, 4)
rbind(cumsum(x), t(sapply(1:3, function(y) c(rep(0, y), cumsum(x[-(1:y)])) )))
#       [,1] [,2] [,3] [,4]
# [1,]    1    3    6   10
# [2,]    0    2    5    9
# [3,]    0    0    3    7
# [4,]    0    0    0    4
like image 20
lukeA Avatar answered Oct 10 '22 17:10

lukeA


Like this:

> x=c(1, 2, 3, 4)

> do.call(rbind, lapply(1:length(x)-1, function(u) {x[0:u]=0;cumsum(x)}))
#     [,1] [,2] [,3] [,4]
#[1,]    1    3    6   10
#[2,]    0    2    5    9
#[3,]    0    0    3    7
#[4,]    0    0    0    4
like image 26
Colonel Beauvel Avatar answered Oct 10 '22 19:10

Colonel Beauvel