Двойной / вложенный для цикла в R - PullRequest
0 голосов
/ 20 декабря 2018

Я столкнулся с определенной проблемой: я хочу получить значения в моей матрице, основываясь на других значениях в матрице, например,

     [,1]     [,2]     [,3]
[1,]  110   0.0000   0.0000
[2,]    0 300.3475   0.0000
[3,]    0   0.0000 820.0785

А теперь я хочу, чтобы сначаластолбец до последней строки значений:

[1,1] = 110
[2,1] = [1,1] * const
[3,1] = [2,1] * const

Во втором столбце:

[2,1] = 0
[2,2] = 300.3475
[3,2] = [2,2] * const

И то же самое для каждого столбца.Таким образом, смысл состоит в том, чтобы получить значение из [i, i], умножить его на const и поместить в [i + 1, i], затем это значение умножить на const и поместить в [i + 2, i].И та же процедура для каждого столбца.Таким образом, приведенная выше матрица будет выглядеть так (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

Я придумал что-то вроде этого:

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
  }
}

И теперь, это работает - ноэто показывает ошибку:

Error in `[<-`(`*tmp*`, j + 1, i, value = bin.mat[j, i] * d) : 
  subscript out of bounds

И, честно говоря, я понятия не имею, почему.Возможно, потому, что я не совсем понимаю, как работает этот цикл, я только что попробовал maaaaaany его варианты, и это единственный, который на самом деле делает то, что я хочу: D И хотя другие вычисления, основанные на этой матрице, неверны, я подозреваю, что до тех пор, покапоскольку он работает для небольшого числа столбцов или строк, он может не работать должным образом для больших.

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Другой подход с использованием apply и 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

Идея состоит в том, чтобы заменить 0 s в нижнем треугольнике на const, значения в верхнем треугольнике на 1 и затем примените cumprod к каждому столбцу.

данные

mat <- structure(c(110, 0, 0, 0, 300.3475, 0, 0, 0, 820.0785), .Dim = c(3L, 
3L), .Dimnames = list(NULL, NULL))
0 голосов
/ 20 декабря 2018

Проблема, по сути, заключается в том, что 3:2 является вектором c(3,2).Поэтому, когда i = 3 вы выходите за пределы при попытке bin.mat[j+1,i].Вот исправление (сохранение цикла)

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
...