R: Zastavenie Slučky, Ak Podmienka je Splnená,

0

Otázka

Ja pracujem s programovací jazyk R. Vytvoril som tieto slučky, ktorý vytvára 1000 náhodných čísel - a potom sa tento proces sa opakuje 10-krát:

results <- list()

for (i in 1:10){

a = rnorm(1000,10,1)
b = rnorm(1000,10,1)


d_i = data.frame(a,b)
d_i$index = 1:nrow(d_i)
d_i$iteration = as.factor(i)

 results[[i]] <- d_i

}



results_df <- do.call(rbind.data.frame, results)

Otázka: chcela by som zmeniť túto slučku tak, že nie len na generovanie 1000 náhodných čísel, to vedie generovanie náhodných čísel, kým splnení určitých podmienok, napríklad: UCHOVÁVAJTE generovanie náhodných čísel, KÝM d_i$a > 10 A d_i$b > 10.

Pomocou "WHILE()" vyhlásenie, snažil som sa to urobiť toto:

results <- list()

for (i in 1:10){

 while (d_i$a > 10 & d_i$b >10) {

a = rnorm(1000,10,1)
b = rnorm(1000,10,1)


d_i = data.frame(a,b)
d_i$index = 1:nrow(d_i)
d_i$iteration = as.factor(i)

 results[[i]] <- d_i

}

}


results_df <- do.call(rbind.data.frame, results)

Problém: No, to sa vráti, nasledujúce varovania (10-krát):

Warning messages:
1: In while (d_i$a > 10 & d_i$b > 10) { :
  the condition has length > 1 and only the first element will be used

A produkuje prázdnu tabuľku:

> results_df

data frame with 0 columns and 0 rows

Môže niekto prosím, pomôžte mi vyriešiť tento problém?

Vďaka!

data-manipulation loops r while-loop
2021-11-23 23:09:34
3

Najlepšiu odpoveď

3

Chybové hlásenia v pôvodnom príspevku sú vzhľadom na skutočnosť, že d_i$a a d_i$b sú vektory s 1,000 prvky a 10 je skalárnym. Preto, R porovnáva prvý prvok d_i$a a prvý prvok d_i$b 10.

Ak chcete vyriešiť chybové hlásenie, musíme porovnať vektor s dĺžkou 1 skalárnym 10. To si vyžaduje reštrukturalizáciu kód generovať náhodné čísla naraz. Z opisu v pôvodnom post, to je jasné, či toto správanie bolo úmyselné.

Som si zjednodušiť problém odstránením súboru 10 replík na ilustráciu, ako vytvoriť údajov rám s náhodných čísel, kým rade má aj a a b s hodnoty je vyšší ako 10.

Po prvé, sme sa vydali semeno, aby sa odpoveď reprodukovateľné, a potom inicializovať niektoré objekty. Nastavením a a b 0 sme sa zabezpečilo, že while() slučka sa vykoná aspoň 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 

S inicializovaný a a bsa while() slučky vyhodnotí TRUE vytvára dve náhodné čísla, priradí hodnota indexu, a píše ich ako údaje rám results zoznam. Logiku pre while() slučky znamená, že ak niektorý a je menší alebo sa rovná 10, alebo b je menší alebo sa rovná 10, slučka udržuje iterating. To sa zastaví, keď obe a a b sú väčšie ako 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
}

Slučka sa zastaví vykonávajúci po deviateho iterácia ako vidíme, tlač výsledné údaje rám po kombinujeme jednotlivé riadky s do.call() a rbind().

df <- do.call(rbind,results)
df

...a výstup:

> 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
>

Všimnite si, že posledný riadok údajov rám má hodnoty viac ako 10 pre oboch a a b.

Viacero replík, z, zatiaľ čo slučky

Na proces zopakujte 10-krát ako je tomu v pôvodnom príspevku, sme zábal operácie for() slučky, a pridať druhý zoznam, combined_results ak chcete uložiť výsledky z každej iterácii.

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,] 

...a výstup pre prvých 4 iterácie vonkajšie slučky:

> 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
> 

Opäť berieme na vedomie, že posledný riadok v každej iterácii (9, 18, 19 a 21) majú hodnoty viac ako 10 pre oboch a a b.

Upozorňujeme, že tento prístup nedokáže využiť vektorizované operácie v R, čo znamená, že namiesto generovania 1,000 náhodné čísla s každou hovoru rnorm()kód založené na while() generuje jedno náhodné číslo, na volanie na rnorm(). Od rnorm() je náročná funkcia, kód, ktorý minimalizuje počet krát rnorm() vykonáva, je žiaduce.

2021-11-24 20:45:06
2

Dúfam, že tieto komentáre pomôcť sledovať, ako to funguje. To hlavne využíva repeat čo je len nekonečnej slučke. To je možné pomocou break kľúčové slovo.

results <- list()


for (i in 1:10){
  
  # do until break
  repeat {
    
    # repeat many random numbers
    a = rnorm(1000,10,1)
    b = rnorm(1000,10,1)
    
    # does any pair meet the requirement
    if (any(a > 10 & b > 10)) {
      
      # put it in a data.frame
      d_i = data.frame(a,b)
      
      # end repeat
      break
    }
  }
  
  # select all rows until the first time the requirement is met
  # it must be met, otherwise the loop would not have ended
  d_i <- d_i[1:which(d_i$a > 10 & d_i$b > 10)[1], ]
  
  # prep other variables
  d_i$index = seq_len(nrow(d_i))
  d_i$iteration = as.factor(i)
  
  results[[i]] <- d_i
  
}
2021-11-24 01:19:52
2

Vymaniť sa zo slučky (počas alebo za), jednoducho na break() po if podmienkou.

out <- vector("integer", 26)
for (i in seq_along(letters)) {
  if(letters[i] == "t") break()
  out[i] <- i+1
}
out
#> [1]  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20  0  0  0  0  0  0  0

Vypukne slučky. Z ?break: ovládanie je prevedené na prvý výrok mimo vnútorné-väčšina slučky.

Avšak, z vašej otázky nie je úplne jasné, prečo sa snažíte to, ako riadenie prietoku nemusí byť vhodné riešenie, ako vektorizované riešením by mohlo existovať. Ďalej, pozor na tom unneccessary veci vo vnútri slučky - to je častou príčinou pre pomalý beh kódu. Tu sme si vziať nejaké veci z pre-slučky, napríklad d_i$iteration a d_i$indexa ešte skončili s rovnakým výsledkom. Pozrite sa na Tretí Kruh.

2021-11-23 23:46:14

V iných jazykoch

Táto stránka je v iných jazykoch

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................