7

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?

Tomas Greif
  • 21,685
  • 23
  • 106
  • 155

5 Answers5

9
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
Roland
  • 127,288
  • 10
  • 191
  • 288
5

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
lukeA
  • 53,097
  • 5
  • 97
  • 100
5

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
Colonel Beauvel
  • 30,423
  • 11
  • 47
  • 87
1
n <- length(vec)
m <- diag(n)
m[sequence(n:1, seq(1, n^2, n + 1L), n)] <- dist(cumsum(c(0, vec)))
m
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    3    6   10
#> [2,]    0    2    5    9
#> [3,]    0    0    3    7
#> [4,]    0    0    0    4
jblood94
  • 10,340
  • 1
  • 10
  • 15
0

A base R one-liner with outer + upper.tri

> t(outer(cumsum(vec), cumsum(c(0, head(vec, -1))), `-`)) * upper.tri(diag(vec), TRUE)
     [,1] [,2] [,3] [,4]
[1,]    1    3    6   10
[2,]    0    2    5    9
[3,]    0    0    3    7
[4,]    0    0    0    4
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81