Reputation: 25
I've encountered a particular problem: What I want to do is to get values in my matrix basing on other values in the matrix, e.g
[,1] [,2] [,3]
[1,] 110 0.0000 0.0000
[2,] 0 300.3475 0.0000
[3,] 0 0.0000 820.0785
And now, I want to have in first column down to last row values of:
[1,1] = 110
[2,1] = [1,1] * const
[3,1] = [2,1] * const
In second column:
[2,1] = 0
[2,2] = 300.3475
[3,2] = [2,2] * const
And the same thing for every column. So the point is to get value from [i, i], multiply it by a const and put into [i+1, i], then this value multiply by a const and put into [i+2, i]. And the same procedure for each column. So the matrix shown above will like this (const = 0.36624):
[,1] [,2] [,3]
[1,] 110.00000 0.0000 0.0000
[2,] 40.28666 300.3475 0.0000
[3,] 14.75468 110.0000 820.0785
I've come up with something like this:
N <- 2
M.dim <- N+1
d <- 0.36624 #const
S0 <- c(110, 320, 820.075) #but length of this vector equals M.dim it's just example)
bin.mat <- matrix(rep(0), M.dim, M.dim)
for(i in 1:M.dim){
for(j in i:N){
bin.mat[i,i] <- S0[i]
bin.mat[j + 1, i] <- bin.mat[j, i] * d
}
}
And now, it is working - but it shows an error:
Error in `[<-`(`*tmp*`, j + 1, i, value = bin.mat[j, i] * d) :
subscript out of bounds
And being honest, I have no idea why. Probably beacuse I don't really get how this loop is working, I just tried maaaaaany variations of it and this is the only one actually doing what I want :D And while other calculations based on this matrix are incorrect, I suspect that as long as it works for low numbers of columns or rows it may not work properly for big ones.
Upvotes: 0
Views: 166
Reputation: 5281
The problem essentially lies in the fact that 3:2
is a vector c(3,2)
. So when i = 3
you get out of bounds when trying bin.mat[j+1,i]
. Here is a fix (keeping a loop)
for(i in 1:M.dim){
bin.mat[i,i] <- S0[i]
if (i >= 3) next # or i > N works as well
for(j in i:N){
bin.mat[j + 1, i] <- bin.mat[j, i] * d
}
}
bin.mat
# returns
[,1] [,2] [,3]
[1,] 110.00000 0.0000 0.000
[2,] 40.28640 320.0000 0.000
[3,] 14.75449 117.1968 820.075
Upvotes: 0
Reputation: 26343
Another approach using apply
and cumprod
const <- 0.36624
mat[lower.tri(mat)] <- const
mat[upper.tri(mat)] <- 1
out <- apply(mat, 2, cumprod)
out[upper.tri(out)] <- 0
out
# [,1] [,2] [,3]
#[1,] 110.00000 0.0000 0.0000
#[2,] 40.28640 300.3475 0.0000
#[3,] 14.75449 109.9993 820.0785
The idea is to replace the 0
s in the lower triangle with const
, the values in the upper triangle with 1
and then apply cumprod
on each column.
data
mat <- structure(c(110, 0, 0, 0, 300.3475, 0, 0, 0, 820.0785), .Dim = c(3L,
3L), .Dimnames = list(NULL, NULL))
Upvotes: 1