Komunikaty o błędach w oryginalnej wiadomości związane z tym, że d_i$a
i d_i$b
są wektorami z 1000 elementów, a 10-skalar. Dlatego R porównuje pierwszy element w d_i$a
i pierwszy element w d_i$b
10.
Aby usunąć komunikat o błędzie, musimy porównać wektor o długości 1 z скаляром 10. To wymaga restrukturyzacji kodu do generowania losowych liczb po jednym na raz. Z opisu w oryginalnym poście nie jest jasne, czy było to zachowanie celowe.
Ułatwię problem, z wyłączeniem zestaw 10 powtórzeń, aby zilustrować, jak stworzyć ramkę danych z przypadkowymi liczbami, aż w wierszu nie pojawią się oba a
i b
z wartościami, niż 10.
Najpierw zadajemy wartość początkową, aby odpowiedź powtarzalne, a następnie инициализируем niektóre obiekty. Ustawienie a
i b
do 0 gwarantujemy, że while()
pętla będzie wykonywana co najmniej raz.
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
i b
w while()
cykl szacuje się na TRUE
generuje dwa losowe liczby, przypisuje wartość indeksu i zapisuje je w postaci ramki danych w results
Lista. Logika dla while()
cykl wskazuje, że jeśli kiedykolwiek a
jest mniejsza lub równa 10 lub b
jest mniejsza lub równa 10, cykl ciągle się powtarzać. To jest zakończone, kiedy oba a
i 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
}
Cykl przerywa wykonanie po dziewiątej iteracji, jak możemy zobaczyć, drukując wyników ramka danych po połączeniu poszczególnych wierszy z do.call()
i rbind()
.
df <- do.call(rbind,results)
df
...i wniosek:
> 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
>
Należy zwrócić uwagę, że ostatnia linia w ramce danych ma znaczenia, przekraczające 10 dla obu a
i b
.
Wielokrotne replikacji pętli while
Aby powtórzyć 10 razy, jak to jest zrobione w oryginalnej wiadomości, możemy stwierdzić operację w for()
wykonaj cykl i dodaj druga lista, combined_results
aby zapisać wyniki każdej iteracji.
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,]
...i dane wyjściowe dla pierwszych 4 iteracji zewnętrznej pętli:
> 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
>
Jeszcze raz należy pamiętać, że ostatni wiersz w każdej iteracji (9, 18, 19 i 21) ma wartości powyżej 10 dla obu a
i b
.
Należy zwrócić uwagę, że podejście to nie korzysta z wektoryzacji operacji w R, co oznacza, że zamiast generowania 1000 liczb losowych przy każdym wywołaniu rnorm()
, kod oparty na while()
generuje jedną losową liczbę dla każdego połączenia rnorm()
. Od tego czasu rnorm()
to ресурсоемкая funkcja kod, który minimalizuje ilość razy rnorm()
najlepiej wykonać.