Сообщения об ошибках в исходном сообщении связаны с тем, что d_i$a
и d_i$b
являются векторами с 1000 элементами, а 10-скаляр. Поэтому R сравнивает первый элемент в d_i$a
и первый элемент в d_i$b
с 10.
Чтобы устранить сообщение об ошибке, нам нужно сравнить вектор длиной 1 со скаляром 10. Это требует реструктуризации кода для генерации случайных чисел по одному за раз. Из описания в оригинальном посте неясно, было ли это поведение преднамеренным.
Я упрощу проблему, исключив набор из 10 повторов, чтобы проиллюстрировать, как создать фрейм данных со случайными числами до тех пор, пока в строке не появятся оба a
и b
со значениями, превышающими 10.
Сначала мы задаем начальное значение, чтобы сделать ответ воспроизводимым, а затем инициализируем некоторые объекты. Установив a
и b
до 0 мы гарантируем, что while()
цикл будет выполняться по крайней мере один раз.
set.seed(950141238) # for reproducibility
results <- list()
a <- 0 # initialize a to a number < 10
b <- 0 # initialize b to a number < 10
i <- 1 # set a counter
Инициализировав a
и b
, в while()
цикл оценивается в TRUE
генерирует два случайных числа, присваивает значение индекса и записывает их в виде фрейма данных в results
Список. Логика для while()
цикл указывает, что если либо a
меньше или равно 10 или b
меньше или равно 10, цикл продолжает повторяться. Это прекращается, когда оба a
и b
больше 10.
while(a <= 10 | b <= 10){
a <- rnorm(1,10,1) # generate 1 random number with mean of 10 and sd of 1
b <- rnorm(1,10,1) # ditto
results[[i]] <- data.frame(index = i,a,b)
i <- i + 1 # increment i
}
Цикл прекращает выполнение после девятой итерации, как мы можем видеть, распечатав результирующий фрейм данных после объединения отдельных строк с do.call()
и rbind()
.
df <- do.call(rbind,results)
df
...и вывод:
> df
index a b
1 1 8.682442 8.846653
2 2 9.204682 8.501692
3 3 8.886819 10.488972
4 4 11.264142 8.952981
5 5 9.900112 10.918042
6 6 9.185120 10.625667
7 7 9.620793 10.316724
8 8 11.718397 9.256835
9 9 10.034793 11.634023
>
Обратите внимание, что последняя строка во фрейме данных имеет значения, превышающие 10 для обоих a
и b
.
Многократные репликации цикла while
Чтобы повторить процесс 10 раз, как это сделано в исходном сообщении, мы заключаем операцию в for()
выполните цикл и добавьте второй список, combined_results
чтобы сохранить результаты каждой итерации.
set.seed(950141238) # for reproducibility
combined_results <- list()
for(iteration in 1:10){
results <- list()
a <- 0 # initialize a to a number < 10
b <- 0 # initialize b to a number < 10
i <- 1 # set a counter
while((a < 10) | (b < 10)){
a <- rnorm(1,10,1) # generate 1 random number with mean of 10 and sd of 1
b <- rnorm(1,10,1) # ditto
results[[i]] <- data.frame(iteration,index = i,a,b)
i <- i + 1 # increment i
}
combined_results[[iteration]] <- do.call(rbind,results)
}
df <- do.call(rbind,combined_results)
df[df$iteration < 5,]
...и выходные данные для первых 4 итераций внешнего цикла:
> df[df$iteration < 5,]
iteration index a b
1 1 1 8.682442 8.846653
2 1 2 9.204682 8.501692
3 1 3 8.886819 10.488972
4 1 4 11.264142 8.952981
5 1 5 9.900112 10.918042
6 1 6 9.185120 10.625667
7 1 7 9.620793 10.316724
8 1 8 11.718397 9.256835
9 1 9 10.034793 11.634023
10 2 1 11.634331 9.746453
11 2 2 9.195410 7.665265
12 2 3 11.323344 8.279968
13 2 4 9.617224 11.792142
14 2 5 9.360307 11.166162
15 2 6 7.963320 11.325801
16 2 7 8.022093 8.568503
17 2 8 10.440788 9.026129
18 2 9 10.841408 10.033346
19 3 1 11.618665 10.179793
20 4 1 10.975061 9.503309
21 4 2 10.209288 12.409656
>
Еще раз отметим, что последняя строка в каждой итерации (9, 18, 19 и 21) имеет значения, превышающие 10 для обоих a
и b
.
Обратите внимание, что этот подход не использует преимущества векторизованных операций в R, что означает, что вместо генерации 1000 случайных чисел при каждом вызове rnorm()
, код, основанный на while()
генерирует одно случайное число для каждого вызова rnorm()
. С тех пор rnorm()
это ресурсоемкая функция, код, который сводит к минимуму количество раз rnorm()
желательно выполнить.