2009-10-12 73 views
11

Làm thế nào để bạn viết đúng vòng lặp for đôi trong R?Double Đối với vòng lặp trong R

Ví dụ, trong CI sẽ làm

int i, j; 
for (i = 1; i < 6; i++) { 
    for (j=i; j <= 3; j++) { 
     printf("%i,%i\n",i,j); 
    } 
    // Do more operations for i > 3... 
} 

đó sẽ tạo ra (nhân tạo) trình tự:

1,1 
1,2 
1,3 
2,2 
2,3 
3,3 

Trong R bạn không nhận được các hành vi tương tự khi bạn viết

for (i in 1:6) { 
    for (j in i:3) { 
     print(paste(i,j,sep=",")) 
    } 
} 

vì vậy tôi đã bị giảm làm một số việc như

for (i in 1:6) { 
    j <- i 
    while (j <= 3) { 
     print(paste(i,j,sep=",")) 
     j <- j+1 
    } 
}  

Có cách nào tốt hơn không?

Như Shane đã đề cập, có lẽ tôi nên làm rõ điều này: Tôi đặc biệt quan tâm đến kiểu mã phù hợp với toán học để giúp sinh viên dễ hiểu hơn. Có vẻ như các sinh viên cảm thấy thoải mái nhất với các vòng for.

Cụ thể, tôi muốn học sinh của mình mô phỏng LIBOR market model. Các động thái của tốc độ chuyển tiếp sẽ được mô phỏng theo cùng một thước đo xác suất. Như vậy, đối với mỗi bước thời gian và mỗi tỷ lệ chuyển tiếp , hiệu chỉnh độ lệch thích hợp \ mu_i cần được tính toán và bổ sung.

+0

Ý bạn là tôi trong 1: (2 * N). Nếu không, chỉ số i của bạn sẽ chỉ nhận giá trị N và 2 * N. –

+0

Vâng, cảm ơn. Tôi đã lấy giá trị ngay bây giờ để làm cho nó rõ ràng hơn. –

+0

Bạn có thể làm cho mục tiêu của bạn rõ ràng hơn một chút: bạn đang cố gắng dạy R cho sinh viên biết C (ví dụ)? Có lẽ có nhiều cách hiệu quả để tạo chuỗi đó, nhưng có vẻ như bạn đặc biệt quan tâm đến() vòng lặp ... – Shane

Trả lời

11

Xin lỗi vì đã hỏi câu hỏi nào có thể là một câu hỏi ngớ ngẩn, nhưng ở mức độ nào R có thể không làm điều này? Điều này hoạt động hoàn toàn tốt cho tôi:

N <- 5 
for (i in 0:(2*N)) { 
    for (j in i:N) { 
     print(paste(i,j,sep=",")) 
    } 
} 

Có thể là bạn không đặt dấu ngoặc đơn vào cuối chuỗi của bạn?

Chỉnh sửa: Tôi hiểu ... bạn muốn thực thi rằng chuỗi i: 3 luôn là < = 3? Tôi không nghĩ rằng có thể với một chuỗi hoặc trong mệnh đề của câu lệnh for. Bạn có thể đặt một break trong vòng lặp, nhưng điều đó không có gì tốt hơn so với phương pháp hiện tại của bạn:

for (i in 1:6) { 
    for (j in i:3) { 
     if(j > 3) break() 
     print(paste(i,j,sep=",")) 
    } 
} 

Dưới đây là một cách khác để tạo ra chuỗi này mà không có một vòng lặp for:

x <- cbind(rep(c(1,2,3), 3), 
    rep(c(1,2,3), each=3)) 

Hoặc với mở rộng.lưới (theo đề nghị của Dirk của):

x <- expand.grid(x=1:3, y=1:3) 

Sau đó, loại bỏ các trường hợp không mong muốn:

x[x[,1] >= x[,2],] 

Sửa 2: này có thể không phù hợp với nhu cầu của bạn, nhưng tôi tin rằng Quantlib có một mô hình thị trường Libor thực hiện. Tôi không chắc đó là exposed in RQuantlib.

+0

Tôi đã chỉnh sửa câu hỏi của mình để hy vọng làm cho nó rõ ràng hơn bây giờ. Cảm ơn. –

+0

Sử dụng "ngắt" là tốt đẹp, điều đó có nghĩa là tôi không cần phải giải thích "trong khi". Cảm ơn. –

+0

'ngắt' không cần dấu ngoặc đơn'() '. – Gregor

9

Bạn có thể tất nhiên tổ bẹ:

R> for (i in 1:3) for (j in 1:3) cat(i,j,i*j, "\n") 
1 1 1 
1 2 2 
1 3 3 
2 1 2 
2 2 4 
2 3 6 
3 1 3 
3 2 6 
3 3 9 
R> 

Có cảm giác chung mà bạn không nên như các cuộc gọi vectorised có thể được dễ dàng hơn để đọc và viết:

R> outer(1:3,1:3, "*") 
    [,1] [,2] [,3] 
[1,] 1 2 3 
[2,] 2 4 6 
[3,] 3 6 9 
R> 

nhưng nếu nó là dễ dàng hơn để phát triển với vòng lặp tiếp theo, sau đó làm như vậy.

Đối với 'chỉ số thứ hai phụ thuộc vào chỉ số đầu tiên', bạn có thể sử dụng lower.tri(), upper.tri() hoặc lập chỉ mục để đạt được điều đó.

R> X <- expand.grid(x=1:3, y=1:3) 
R> X <- X[ X$x >= X$y, ] 
R> outer(X$x, X$y, "*") 
    [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 1 1 1 2 2 3 
[2,] 2 2 2 4 4 6 
[3,] 3 3 3 6 6 9 
[4,] 2 2 2 4 4 6 
[5,] 3 3 3 6 6 9 
[6,] 3 3 3 6 6 9 
R> 
+0

Cảm ơn, sử dụng bên ngoài có lẽ là một cách tốt để làm điều đó, tôi sẽ cung cấp cho nó một đi. Mặc dù nó làm cho các thuật toán không còn trông giống như toán học, do đó, nó làm cho nó khó khăn cho các sinh viên của tôi để hiểu. –

5

Vấn đề ở đây là i:3 có ý nghĩa khi i>3. Ví dụ: 5:3 cho số (5,4,3). Tất cả những gì bạn cần là một câu lệnh if đơn giản để ngăn chặn vòng lặp thứ hai đang chạy khi i>3.

for (i in 1:6) { 
    if(i < 4) { 
     for (j in i:3) { 
      print(paste(i,j,sep=",")) 
     } 
    } 
    # Do more operations for i > 3... 
} 

Tuy nhiên, nếu có thể, hãy cố tránh vòng lặp rõ ràng. Câu trả lời của Dirk và Shane cung cấp một số ý tưởng về cách thực hiện điều này.

+0

Điều này là tốt đẹp, nó có nghĩa là tôi không cần phải giải thích những gì "trong khi" nào. –

Các vấn đề liên quan