Menu

R'de For Döngüleri: Söz Dizimi, seq_along, break, next ve Ne Zaman Döngü Kurmamalı

R'de for döngüleri nasıl çalışır - vektörler ve indeksler üzerinde dönmek, büyüyen vektör tuzağına düşmeden sonuç toplamak, next ile break ve vektörleştirilmiş bir çağrının döngüyü ne zaman yendiği.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Temel for Döngüsü

R'de bir for döngüsü, bir vektörün ya da listenin her elemanı için bir kod bloğunu bir kez çalıştırır. Döngü değişkeni her değeri sırayla alır:

Üç eleman, üç tur. Kurulacak bir sayaç ya da sürdürülecek bir koşul yoktur - for (fruit in fruits) "fruits içindeki her fruit için" diye okunur ve tam olarak bunu yapar. Aynı biçim bir listenin elemanları, bir sayı dizisi (for (i in 1:10)) ya da names() yoluyla herhangi bir şeyin isimleri üzerinde de yinelenir.

Döngü İçinde Yazdırmak print() veya cat() İster

Konsolda x yazmak değerini yazdırır. Bir döngü gövdesinin içinde ise yazdırmaz - otomatik yazdırma yalnızca en üst düzeyde gerçekleşir ve döngü içindeki yalın bir ifade değerlendirilip atılır:

Yani bir döngü "hiçbir şey yapmadığında" kontrol edilecek ilk şey budur. Herhangi bir değere hızlıca göz atmak için print(), bir çıktı satırını kendiniz kurarken cat() kullanın ("\n" unutmayın - cat() eklemez).

seq_along() ile İndeksler Üzerinde Dönmek

Bazen değerin yanı sıra konuma da ihtiyacınız olur - aynı indekste başka bir vektöre yazmak ya da numaralı bir liste yazdırmak için. İndeksler üzerinde seq_along() ile dönün:

Eski kodda for (i in 1:length(prices)) göreceksiniz ve bu gerçek bir hatayı barındırır. Vektör boş olduğunda length() 0'dır ve 1:0 "hiç yineleme yok" anlamına gelmez - iki nokta üst üste geriye sayar:

1:length(empty) üzerindeki bir döngü iki kez çalışır ve var olmayan elemanları indeksler (empty[1] NA'dır ve atamalar hayalet girdiler oluşturur). seq_along() boş bir vektör için boş bir dizi döndürür, dolayısıyla döngü gövdesi hiç çalışmaz. seq_along() alışkanlık olsun; kardeşi seq_len(n), elinizde vektör yerine bir sayı olduğunda aynı işi yapar.

Sonuç Toplama: Büyütmeyin, Önceden Ayırın

Sonuçları biriktirmek için doğal ilk içgüdü şuna benzer:

squares <- c()
for (i in 1:10000) {
  squares <- c(squares, i^2)   # copies the ENTIRE vector every pass
}

Çalışır, ama her c(squares, ...) yepyeni bir vektör ayırır ve tüm eski elemanları içine kopyalar. Sonunda 10.000 sayı üretmek için kabaca 50 milyon sayı kopyalamış olursunuz. Bu büyüyen vektör anti-kalıbı, insanların R döngülerine yavaş demesinin bir numaralı nedenidir.

Çözüm: sonucu önce tam boyutunda oluşturun, sonra indeksle atayın:

Sayı olmayan sonuçlarda aynı fikir character(n), logical(n) ya da rastgele şeylerden oluşan bir liste için vector("list", n) ile geçerlidir. Önceden yer ayrılmış döngüler gayet hızlıdır.

next ve break

İki anahtar sözcük bir döngüyü gövdesinin içinden yönlendirir: next mevcut turu terk edip bir sonraki elemana atlar; break ise döngüden tamamen çıkar.

Bu 2 4 6 8 yazdırır: tek değerler next ile atlanır ve 10 geldiğinde break döngüyü yazdırmadan önce bitirir. Durumları erkenden elemek için next kullanın (ana gövdeyi girintisiz tutar), bir döngü aradığını bulduğunda ve devam etmek için nedeni kalmadığında break kullanın.

İç İçe Döngüler

Bir döngü gövdesi başka bir döngü içerebilir. İç döngü, dış döngünün her turu için baştan sona çalışır - klasik gösterim bir çarpım tablosudur:

Her i satırı için iç döngü tüm j sütunlarını dolaşır ve satırın yeni satır karakteri iç döngü bittikten sonra yazdırılır. İç içe döngüler iki düzeyde sorunsuzdur; üç ya da daha fazlasında gövde genellikle bir fonksiyona dönüşmek ister ya da hesabın tamamı bir outer() veya matris işlemi olmak ister.

İç içe koyma, vektörlerden oluşan bir liste üzerinde dönmeyi de kapsar - dış döngü liste üzerinde, iç döngü (ya da daha iyisi, vektörleştirilmiş bir çağrı) her eleman üzerinde:

Sonunda hiç iç döngü olmadığına dikkat edin - mean(), tüm iç vektörü tek bir çağrıda halleder. Bu gözlem geneller ve bizi dürüst kısma getirir.

Ne Zaman Döngü Kurmamalı

R vektörleştirilmiş bir dildir: temel işlemleri zaten bütün vektörler üzerinde aynı anda çalışır. Her elemanı teker teker dönüştüren bir döngü, çoğu zaman tek satırlık bir ifadeyi yazmanın uzun yoludur:

Var olduğu her yerde vektörleştirilmiş biçimi tercih edin - daha kısadır, yanlış yapması zordur ve daha hızlıdır. Bir listenin her elemanına bir fonksiyon uygulamak için apply ailesi (sapply, lapply, vapply) aynı rolü oynar.

Ama bunu "döngüler kötüdür" diye kargo kültüne çevirmeyin. Yinelemeler öncekilere bağlı olduğunda (birikimli durum, simülasyonlar), dosya yazmak gibi yan etkiler ürettiğinizde ya da basitçe döngü sizin ve okurlarınızın bir bakışta anladığı sürüm olduğunda döngü doğru araçtır. Net bir döngü, kimsenin çözemediği zekice bir tek satırlığı yener.

Buradan Ne Çıkarıyorsunuz

  • for (x in v) { ... }, gövdeyi eleman başına bir kez çalıştırır - sayaç muhasebesi yok.
  • Döngü içinde print() ya da cat() ile açıkça yazdırın; yalın ifadeler atılır.
  • Konumlar üzerinde seq_along(v) ile dönün, asla 1:length(v) ile değil - ikincisi boş bir vektörde iki kez çalışır.
  • Sonuçlar için numeric(n) / vector("list", n) ile önceden yer ayırın ve indeksle atayın; c() ile büyütmek her turda her şeyi kopyalar.
  • next bir turu atlar, break çıkar; var olduğunda vektörleştirilmiş işlemleri tercih edin, ama okunabilir bir döngüden korkmayın.

Sırada: eleman başına bir kez değil, bir şey olana kadar çalışan döngüler - while ve repeat.

Sıkça Sorulan Sorular

R'de for döngüsü nasıl yazılır?

for (x in v) { ... } - döngü değişkeni x, v vektörünün (ya da listesinin) her elemanını sırayla alır ve gövde eleman başına bir kez çalışır. Değerler yerine konumlar üzerinde dönmek için for (i in seq_along(v)) kullanın ve v[i] ile indeksleyin.

R'de neden 1:length(v) yerine seq_along kullanılır?

v boş olduğunda length(v) 0'dır, dolayısıyla 1:length(v) 1:0 olur - iki elemanlı c(1, 0) vektörü - ve döngü gövdesi var olmayan elemanlar üzerinde iki kez çalışır. seq_along(v), boş bir vektör için boş bir dizi döndürür, böylece döngü doğru biçimde sıfır kez çalışır.

R'deki for döngüm neden hiçbir şey yazdırmıyor?

R'nin otomatik yazdırması yalnızca konsolun en üst düzeyinde yazılan ifadeler için gerçekleşir. Bir döngü gövdesinin içinde x gibi yalın bir ifade değerlendirilir ve atılır. Onu print(x) içine sarın ya da çıktıyı kendiniz biçimlendirmek istediğinizde cat(...) kullanın.

R'de for döngüleri yavaş mıdır?

Döngünün kendisi sorunsuzdur - yavaş olan, döngü içinde result <- c(result, ...) ile bir vektörü büyütmektir; bu her turda tüm vektörü kopyalar. numeric(n) ya da vector("list", n) ile önceden yer ayırıp indeksle atama yaparsanız döngü gayet iyi performans gösterir. Yine de vektörleştirilmiş bir işlem ya da apply ailesinden bir çağrı aynı fikri ifade ediyorsa, bu genellikle hem daha hızlı hem daha nettir.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA