Mesajele de eroare, în original post se datorează faptului că d_i$a
și d_i$b
sunt vectori cu 1.000 de elemente și 10 este un scalar. Prin urmare, R compară primul element din d_i$a
și primul element din d_i$b
cu 10.
Pentru a rezolva mesaj de eroare de care avem nevoie pentru a compara un vector cu lungimea de 1 scalar 10. Acest lucru necesită restructurarea cod pentru a genera numere aleatoare la un moment dat. Din descrierea din postul original, nu este clar dacă acest comportament a fost intenționată.
Voi simplifica problema prin eliminarea set de 10 replici pentru a ilustra cum de a crea un cadru de date cu numere aleatoare până când un rând are ambele a
și b
cu valori mai mari decât 10.
În primul rând, ne-am stabilit o sămânță pentru a face răspunsul reproductibile, și apoi a inițializa unele obiecte. Prin stabilirea a
și b
la 0 asigurăm că while()
bucla se va executa cel puțin o dată.
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
Având inițializat a
și b
, la while()
bucla se evaluează la TRUE
generează două numere aleatoare, atribuie o valoare index, și le scrie ca un cadru de date la results
lista. Logica pentru while()
bucla indică faptul că dacă a
este mai mică sau egală cu 10 sau b
este mai mică sau egală cu 10, buclă continuă iterarea. Se oprește atunci când ambele a
și b
sunt mai mari decât 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
}
Bucla se oprește de executare după nouă repetare după cum putem vedea de imprimare rezultat cadru de date după ce ne-am combina rânduri individuale cu do.call()
și rbind()
.
df <- do.call(rbind,results)
df
...și la ieșire:
> 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
>
Observați că ultimul rând, în cadru de date are valori mai mari decât 10 pentru ambele a
și b
.
Mai multe replici de buclă în timp ce
Pentru a repeta procesul de 10 ori cum se face în original post, vom încheia operațiunea într-un for()
buclă, și se adaugă o a doua listă, combined_results
pentru a salva rezultatele de la fiecare iterație.
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 de ieșire pentru primele 4 iterații a buclei exterioare:
> 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
>
Din nou observăm că ultimul rând, în fiecare iterație (9, 18, 19 și 21) au valori mai mari decât 10 pentru ambele a
și b
.
Rețineți că această abordare nu reușește să profite de vectorized operațiuni în R, în sensul că în loc de a genera 1.000 de numere aleatoare cu fiecare apel pentru a rnorm()
, codul bazat pe o while()
generează un singur număr aleator pe sunați pentru a rnorm()
. Deoarece rnorm()
este o resursă intensivă funcția, codul care minimizează numărul de ori rnorm()
execută este de dorit.