As mensagens de erro no post original, devido ao fato de que d_i$a
e d_i$b
são vetores com 1000 elementos e 10 é um escalar. Portanto, R, compara-se o primeiro elemento d_i$a
e o primeiro elemento na d_i$b
com 10.
Para resolver a mensagem de erro precisamos comparar um vetor com comprimento de 1 a escalar 10. Isso requer a reestruturação do código para gerar os números aleatórios uma de cada vez. A partir da descrição no post original, não está claro se este comportamento foi intencional.
Vou simplificar o problema, eliminando o conjunto de 10 repetições para ilustrar como criar um quadro de dados com números aleatórios até que uma linha tem tanto a
e b
com valores maiores que 10.
Primeiro, vamos definir uma semente para fazer a resposta pode ser reproduzido e, em seguida, inicializar alguns objetos. Por definição a
e b
para 0, podemos garantir que os while()
loop será executado pelo menos uma vez.
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
Ter inicializado a
e b
o while()
loop avalia a TRUE
gera dois números aleatórios, atribui um valor de índice, e escreve-los como um quadro de dados para o results
a lista. A lógica para a while()
loop indica que se a
é menor ou igual a 10 ou b
é menor ou igual a 10, o loop continua a iteração. Ele pára quando ambos a
e b
são maiores do que 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
}
O ciclo pára a execução, após a nona iteração como podemos ver através da impressão resultante quadro de dados depois de combinar as linhas individuais com do.call()
e rbind()
.
df <- do.call(rbind,results)
df
...e a saída:
> 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
>
Observe que a última linha do quadro de dados tem valores maiores que 10 para os dois a
e b
.
Várias repetições do loop while
Para repetir o processo 10 vezes como é feito na postagem original, nós enrole a operação em um for()
loop, e adicionar uma segunda lista, combined_results
para salvar os resultados de cada iteração.
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,]
...e a saída para as 4 primeiras iterações do loop externo:
> 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
>
Novamente nota-se que a última linha em cada iteração (9, 18, 19 e 21) têm valores maiores que 10 para os dois a
e b
.
Nota-se que esta abordagem não tira vantagem de vetorizados operações em R, o que significa que, em vez de gerar mais de 1.000 números aleatórios com cada chamada para rnorm()
o código com base em uma while()
gera um único número aleatório por chamada rnorm()
. Desde rnorm()
é um recurso intensivo de função, o código que minimiza o número de vezes rnorm()
executa é desejável.