Double Для циклов в R
Как вы правильно пишете двойной цикл for
в R?
Например, в C я бы сделал
int i, j;
for (i = 1; i < 6; i++) {
for (j=i; j <= 3; j++) {
printf("%i,%i\n",i,j);
}
// Do more operations for i > 3...
}
который будет генерировать (искусственную) последовательность:
1,1
1,2
1,3
2,2
2,3
3,3
В R вы не получаете такого же поведения, когда пишете
for (i in 1:6) {
for (j in i:3) {
print(paste(i,j,sep=","))
}
}
поэтому я был сведен к выполнению чего-то вроде
for (i in 1:6) {
j <- i
while (j <= 3) {
print(paste(i,j,sep=","))
j <- j+1
}
}
Есть ли лучший способ?
Как упоминал Шейн, возможно, я должен сделать это ясно: меня особенно интересует стиль кода, соответствующий математике, чтобы облегчить понимание учениками. Кажется, что ученики наиболее удобны с циклами for
.
В частности, я хочу, чтобы мои ученики моделировали модель рынка LIBOR. Динамику форвардной скорости следует моделировать с той же вероятностной мерой. Таким образом, для каждого временного шага и каждого
прямой скорости, необходимо вычислить соответствующую коррекцию дрейфа\mu_i.
Ответы
Ответ 1
Извините за вопрос, что потенциально является немым вопросом, но в каком смысле R не может этого сделать? Это отлично работает для меня:
N <- 5
for (i in 0:(2*N)) {
for (j in i:N) {
print(paste(i,j,sep=","))
}
}
Может быть, вы просто не помещали круглые скобки вокруг конца вашей последовательности?
Изменить: Я вижу... вы хотите обеспечить, чтобы последовательность i: 3 всегда <= 3? Я не думаю, что это возможно с любой последовательностью или внутри предложения for for. Вы можете установить разрыв в цикле, но это не лучше вашего текущего подхода:
for (i in 1:6) {
for (j in i:3) {
if(j > 3) break()
print(paste(i,j,sep=","))
}
}
Здесь другой способ генерации этой последовательности без цикла for:
x <- cbind(rep(c(1,2,3), 3),
rep(c(1,2,3), each=3))
Или с помощью expand.grid(в соответствии с предложением Dirk):
x <- expand.grid(x=1:3, y=1:3)
Затем удалите ненужные случаи:
x[x[,1] >= x[,2],]
Изменить 2: Это может не соответствовать вашим потребностям, но я считаю, что Quantlib имеет реализацию модели рынка Libor. Я не уверен, если он открыт в RQuantlib.
Ответ 2
Вы можете, конечно, петли гнезда:
R> for (i in 1:3) for (j in 1:3) cat(i,j,i*j, "\n")
1 1 1
1 2 2
1 3 3
2 1 2
2 2 4
2 3 6
3 1 3
3 2 6
3 3 9
R>
Существует общее мнение о том, что вы не должны, поскольку векторизованные вызовы могут быть проще читать и писать:
R> outer(1:3,1:3, "*")
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 4 6
[3,] 3 6 9
R>
но если его легче разрабатывать с помощью следующих циклов, сделайте это.
Что касается "второго индекса, зависящего от первого индекса", вы можете использовать lower.tri(), upper.tri() или индексирование для достижения этого.
R> X <- expand.grid(x=1:3, y=1:3)
R> X <- X[ X$x >= X$y, ]
R> outer(X$x, X$y, "*")
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 2 2 3
[2,] 2 2 2 4 4 6
[3,] 3 3 3 6 6 9
[4,] 2 2 2 4 4 6
[5,] 3 3 3 6 6 9
[6,] 3 3 3 6 6 9
R>
Ответ 3
Проблема здесь в том, что i:3
имеет смысл, когда i>3
. Например, 5:3
дает (5,4,3)
. Все, что вам нужно, это простой оператор if, чтобы предотвратить запуск второго цикла, когда i>3
.
for (i in 1:6) {
if(i < 4) {
for (j in i:3) {
print(paste(i,j,sep=","))
}
}
# Do more operations for i > 3...
}
Однако, если возможно, попытайтесь избежать явного цикла. Ответы Дирка и Шейна дают некоторые идеи о том, как это сделать.