สเปนเซอร์รี้ดครับ R:หยุดไปเรื่อยๆตอนเป็นเงื่อนมันเจอ

0

คำถาม

ฉันทำงานกับสเปนเซอร์รี้ดครับ R ตั้งโปรแกรมภาษาด้วย ฉันสร้างผู้ติดตามวงนั่นสร้า 1000 สุ่มตัวเลข-แล้วทำซ้ำการทำงานของมัน 10 ครั้ง:

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)

คำถาม: ฉันอยากจะเปลี่ยนแปลงวงเรื่องนั้นแทนที่จะเป็นเพียงกำลังสร้าง 1000 สุ่มตัวเลขมันทำให้กำลังสร้างการสุ่มตัวเลขจนกระทั่งสภาพเป็นพบตัวอย่างเช่น:ต่อกำลังสร้างการสุ่มตัวเลขจนกระทั่ d_i$เป็น>10 และ d_i$บี>อายุ 10 ขวบอยู่เลย

ใช้"ขณะที่()"แถลงการณ์ผมพยายามจะทำอย่างนี้:

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)

ปัญหา: อย่างไรก็ตามนี้จะคืนค่ากลับมาเป็นตามการแจ้งเตือน(10 ครั้ง):

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

และได้เป็นที่ว่างเปล่าโต๊ะ:

> results_df

data frame with 0 columns and 0 rows

ใครก็ได้ช่วยฉันแก้ปัญหานี้?

ขอบคุณ!

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

คำตอบที่ดีที่สุด

3

ข้อผิดพลาดข้อความดั้งเดิมโพสเป็นเนื่องจากความจริงที่ว่า d_i$a แล้ว d_i$b เป็น vectors กับ 1,000 ส่วนประกอบและ 10 เป็น scalar. ดังนั้น,สเปนเซอร์รี้ดครับ R compares นคนแรกธาตุใน d_i$a และครั้งแรกธาตุใน d_i$b กับอายุ 10 ขวบอยู่เลย

ที่จะต้องแก้ไขข้อผิดพลาดข้อความเราต้องการที่จะเปรียบเทียบนเว็กเตอกับความยาว 1 ค scalar อายุ 10 ขวบอยู่เลย นี่ต้องการ restructuring รหัสสร้างการสุ่มตัวเลขหนึ่งในเวลา. จากรายละเอียดในดั้งเดิมโพสมันไม่ปรากฏว่าพฤติกรรมคือเขาเจตนาทำ

ฉันจะ simplify ปัญหาโดยการกำจัดตั้ง 10 replications จะ illustrate วิธีที่จะสร้างข้อมูลของเฟรมกับการสุ่มตัวเลขจนกระทั่งเป็นแถวมีทั้งสอง a แล้ว b กับค่าของสิ่งที่ยิ่งใหญ่กว่าอายุ 10 ขวบอยู่เลย

ก่อนอื่นเราตั้งเป็นเมล็ดพันธ์ที่จะทำให้คำตอบ reproducible และจากนั้นก็เริ่มการใช้งานบางสิ่ง. โดยการตั้งค่า 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() ว evaluates ต้อง TRUE สร้างการสุ่มตัวเลข assigns เป็นดัชนีค่าและเขียนมันมันเป็นข้อมูลของเฟรมให้ค results รายการ ที่ตรรกะสำหรับ while() เรื่องแสดงให้เห็นว่าถ้าเธอคนใดคน a น้อยกว่าหรือเท่ากับ 10 หรือ b น้อยกว่าหรือเท่ากับ 10,วงด iterating. มันหยุดเมื่อทั้งสอง 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.

หลาย replications ของในขณะที่วง

การที่จะทำซ้ำในระบวนการ 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.

โปรดจำไว้ว่ามันเข้าใกล้ล้มเหลวที่จะสามารถหาประโยชน์จาก vectorized ปฏิบัติการในสเปนเซอร์รี้ดครับ R หมายถึงว่าแทนที่จะเป็นกำลังสร้าง 1,000 สุ่มตัวเลขกับโทรไป rnorm()รหัสจากพื้นฐาน while() สร้านเดียวแรนดอมจำนนต่อโทรไป rnorm(). ตั้งแต่ rnorm() เป็นทรัพยากรเจาะตลาดกลุ่มฟังก์ชันรหัสนั่น minimizes จำนวนครั้ง rnorm() executes คือ desirable.

2021-11-24 20:45:06
2

ฉันหวังว่าความคิดเห็นมากขนาดช่วยตามวิธีการทำงานของมัน มันจุดประสงค์หลักทำให้ใช้ repeat ซึ่งนั่นเป็นแค่ๆ. มันสามารถจะหยุดใช้ break คำค้น.

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

ออกไปจากของวง(ในขณะที่หรือสำหรับ),ลงทางจริงๆเมื่ออาทิตย์ที่ break() หลังจากที่ if ดร.ลอว์สันป่วย

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

จะออกจากห้องเหมือนเธอได้ติดตั้ง จาก ?break:การควบคุมถูกส่งตัวไปที่แรกแถลงการณ์ด้านนอกภายใน-ส่งข่าวด้วย

อย่างไรก็ตามจากคำถามของคุณมันไม่ใช่ทั้งหมดเคลียร์ทำไมคุณกำลังพยายามนี้-ช่างควบคุมการอาจไม่ใช่ที่ที่เหมาะสมทางออกเป็น vectorized แก้ปัญหาอาจจะมีตัวตน ไกลกว่านี้ระวังของการทำ unneccessary สิ่งที่อยู่ในวง-มันเป็นเหมือนกันเพราะสำหรับวิ่งช้าเป็นรหัสมอส ที่นี่เราจะเอาของบางอย่างออกมาจากสำหรับ-วอย่างเช่น d_i$iteration แล้ว d_i$indexและยังคงลงเอยกับเดียวกับผลลัพธ์. ดู คนที่สามวงเวทย์.

2021-11-23 23:46:14

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

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

ดังอยู่ในนี้หมวดหมู่

ดังคำถามอยู่ในนี้หมวดหมู่