Lewati ke konten utama

Tutorial Loop di R - Penggunaan dan Alternatif

Tutorial tentang loop di R yang membahas konstruksi yang tersedia di R untuk perulangan. Temukan alternatif dengan fitur vektorisasi R.
Diperbarui 28 Sep 2026  · 15 mnt Baca

Jelajahi bersama AI

ChatGPTClaudePerplexity

Tutorial loop R ini akan menelusuri konstruksi yang tersedia di R untuk perulangan, kapan konstruksi tersebut sebaiknya digunakan, dan bagaimana memanfaatkan alternatif, seperti fitur vektorisasi R, untuk menjalankan tugas perulangan Anda dengan lebih efisien.

Artikel ini akan menyajikan beberapa contoh loop lalu mengkritik dan menyingkirkannya demi alternatif tervektorisasi yang lebih populer dari sekian banyak yang tersedia di kumpulan library R yang kaya.

Secara umum, saran dari tutorial loop R ini adalah: pelajari tentang loop. Loop memberi Anda pandangan terperinci mengenai apa yang seharusnya terjadi pada level dasar sekaligus memberikan pemahaman tentang data yang Anda manipulasi.

Dan setelah Anda benar-benar memahami loop, tinggalkanlah loop.

Curahkan upaya Anda untuk mempelajari alternatif tervektorisasi. Ini akan terbayar dari sisi efisiensi.

Untuk berlatih secara interaktif, coba bab tentang loop di kursus R tingkat menengah kami.

Apa itu Loop?

“Looping”, “cycling”, “iterating” atau sekadar mereplikasi instruksi adalah praktik lama yang muncul jauh sebelum komputer ditemukan. Ini tak lain adalah mengotomatisasi proses multi-langkah dengan mengatur urutan tindakan atau proses “batch” dan dengan mengelompokkan bagian-bagian yang perlu diulang.

Semua bahasa pemrograman modern menyediakan konstruksi khusus yang memungkinkan pengulangan instruksi atau blok instruksi.

Secara garis besar, ada dua jenis konstruksi khusus atau loop dalam bahasa pemrograman modern. Beberapa loop dijalankan untuk jumlah tertentu yang sudah ditentukan, dikendalikan oleh pencacah atau indeks, yang dinaikkan pada setiap siklus iterasi. Ini adalah bagian dari keluarga loop for.

Di sisi lain, beberapa loop didasarkan pada pemicu dan verifikasi suatu kondisi logis. Kondisi diuji pada awal atau akhir konstruksi loop. Varian ini masing-masing termasuk dalam keluarga loop while atau repeat.

Pengenalan Loop di R

Menurut manual R base, di antara perintah alur kendali, konstruksi loop adalah for, while, dan repeat, dengan klausa tambahan break dan next.

Ingat bahwa perintah alur kendali adalah perintah yang memungkinkan program bercabang di antara alternatif, atau “mengambil keputusan”, begitu istilahnya.

Anda selalu dapat melihat perintah alur kendali ini dengan memanggil ?Control di baris perintah RStudio.

?Control

Bagan alir berikut menunjukkan struktur loop R:

flow chart r loop structures

For Loop di R

Bagian-bagian berikut akan meninjau lebih dekat setiap struktur yang ditampilkan pada gambar di atas. Kita akan memulai pembahasan dengan struktur di sebelah kiri, lalu berlanjut ke struktur di sebelah kanan secara bertahap.

Untuk pengantar video tentang for loop dan latihan lanjutan, coba bab For Loop di kursus R tingkat menengah kami.

Penjelasan For Loop

Struktur loop ini, terdiri dari kotak persegi panjang ‘init’ (atau inisialisasi), simbol keputusan berbentuk wajik, dan kotak persegi panjang i1 dijalankan sejumlah kali yang diketahui.

Dalam istilah flowchart, kotak persegi panjang berarti sesuatu seperti “lakukan sesuatu yang tidak melibatkan keputusan”. Sementara itu, wajik disebut “simbol keputusan” dan menerjemah menjadi pertanyaan yang hanya memiliki dua jawaban logis, yaitu True (T) atau False (F).

Catatan bahwa untuk menyederhanakan, simbol lain yang mungkin ada dihilangkan dari gambar.

Satu atau lebih instruksi di dalam kotak inisialisasi diikuti oleh evaluasi kondisi pada sebuah variabel yang dapat mengambil nilai dalam suatu urutan tertentu. Pada gambar, ini diwakili oleh simbol wajik: simbol tersebut berarti “apakah nilai saat ini dari variabel v termasuk dalam urutan seq?”.

Dengan kata lain, Anda menguji apakah nilai saat ini dari v berada dalam rentang yang ditentukan. Anda biasanya mendefinisikan rentang ini di inisialisasi, dengan sesuatu seperti 1:100 untuk memastikan loop dimulai.

Jika kondisi tidak terpenuhi dan hasilnya False, loop tidak pernah dijalankan. Ini ditunjukkan oleh panah longgar di sebelah kanan struktur loop for. Program kemudian akan mengeksekusi instruksi pertama yang ditemukan setelah blok loop.

Jika kondisi terpenuhi, sebuah instruksi —atau blok instruksi— i1 dijalankan. Dan mungkin blok instruksi ini adalah loop lain. Dalam kasus seperti itu, ini disebut loop bertingkat (nested loop).

Setelah selesai, kondisi kemudian dievaluasi lagi. Ini ditunjukkan oleh garis dari i1 kembali ke atas, tepat setelah kotak inisialisasi. Di R —dan di Python, hal ini dapat diekspresikan dalam bahasa Inggris biasa, dengan menanyakan apakah variabel kita termasuk dalam suatu rentang nilai atau tidak.

Catatan bahwa di bahasa lain, misalnya C, kondisinya dibuat lebih eksplisit dengan penggunaan operator logika, seperti lebih besar atau lebih kecil dari, sama dengan, …

Berikut contoh for loop sederhana:

# Create a vector filled with random normal values
u1 <- rnorm(30)
print("This loop calculates the square of the first 10 elements of vector u1")

# Initialize `usq`
usq <- 0. 

for (i in 1:10) {
    # i-th element of `u1` squared into `i`-th position of `usq`
    usq[i] <- u1[i] * u1[i]
    print(usq[i])
}

print(i)

Blok for berada dalam kurung kurawal. Ini dapat diletakkan segera setelah kondisi uji atau di baris berikutnya, sebaiknya diikuti indentasi. Tidak ada yang wajib, tetapi kurung kurawal jelas meningkatkan keterbacaan kode Anda dan memudahkan menemukan blok loop dan potensi error di dalamnya.

Catatan bahwa vektor kuadrat, usq, diinisialisasi. Ini tidak akan diperlukan dalam kode RStudio biasa, tetapi dalam versi markup, knitr tidak akan melakukan kompilasi karena referensi ke vektor tidak ditemukan sebelum digunakan dalam loop, sehingga memunculkan error di RStudio. Untuk informasi lebih lanjut tentang knitr, kunjungi halaman R Markdown.

For Loop Bertingkat

Sekarang setelah Anda tahu for loop juga bisa ditumpuk, Anda mungkin bertanya-tanya mengapa dan kapan Anda akan menggunakannya dalam kode.

Misalnya, Anda ingin memanipulasi array dua dimensi dengan mengatur elemennya ke nilai tertentu.

Maka Anda bisa melakukan sesuatu seperti ini:

# Insert your own integer here
my_int <- 42

nr <- as.integer(my_int)

# Create a `n` x `n` matrix with zeros
mymat <- matrix(0, nr, nr)

# For each row and for each column, assign values based on position
# These values are the product of two indexes
for (i in 1:dim(mymat)[1]) {
    for (j in 1:dim(mymat)[2]) {
        mymat[i, j] = i * j
    }
}

Tips: untuk informasi lebih lanjut tentang fungsi matrix(), kunjungi R Documentation.

You have two nested for loops in the code chunk above and thus two sets of curly braces, each with its own block and governed by its own index. That is, i runs over the lines and j runs over the columns.
 
Apa yang dihasilkan?

Anda membuat tabel perkalian yang sangat familiar dan seharusnya Anda hafal di luar kepala.

Anda juga dapat memilih bilangan bulat dan kemudian menghasilkan tabel sesuai pilihan Anda: Anda dapat menetapkan bilangan bulat ke sebuah variabel jika tabel berbentuk persegi atau ke dua variabel jika tabel berbentuk persegi panjang. Variabel ini kemudian akan berfungsi sebagai batas atas untuk indeks i dan j.

# Show the first 10x10 chunk or the first `nr` x `nr` chunk
if (nr > 10) {
    mymat[1:10, 1:10]
} else
    mymat[1:nr, 1:nr]

Catatan bahwa untuk mencegah pengguna membanjiri layar dengan tabel berukuran besar, Anda menaruh kondisi di akhir untuk mencetak potongan 10 x 10 pertama, hanya jika pengguna meminta bilangan bulat lebih besar dari 10. Jika tidak, potongan n x n akan dicetak.

Kode lengkapnya terlihat seperti ini:

# Insert your own integer here
my_int <- 42

nr <- as.integer(my_int)

# Create a `n` x `n` matrix with zeroes
mymat <- matrix(0, nr, nr)

While Loop

Loop while, yang berada di tengah gambar di atas, terdiri dari blok inisialisasi seperti sebelumnya, diikuti oleh kondisi logis. Kondisi ini biasanya diekspresikan dengan perbandingan antara variabel kendali dan suatu nilai, menggunakan lebih besar dari, lebih kecil dari, atau sama dengan; tetapi ekspresi apa pun yang mengevaluasi ke nilai logis, True atau False, sah.

Jika hasilnya False (F), loop tidak pernah dijalankan, seperti ditunjukkan oleh panah longgar di sebelah kanan gambar. Program kemudian akan mengeksekusi instruksi pertama yang ditemukan setelah blok loop.

Jika True (T), instruksi atau blok instruksi i1 dieksekusi berikutnya.

Perhatikan bahwa instruksi tambahan atau blok instruksi i2 ditambahkan: ini berfungsi sebagai pembaruan untuk variabel kendali, yang dapat mengubah hasil kondisi di awal loop, tetapi ini tidak wajib. Atau mungkin Anda ingin menambahkan kenaikan pada pencacah untuk melacak jumlah iterasi yang dijalankan. Iterasi berhenti setelah kondisi mengevaluasi ke false.

Formatnya adalah while(cond) expr, di mana cond adalah kondisi yang diuji dan expr adalah sebuah ekspresi.

Misalnya, loop berikut meminta pengguna dengan User Defined Function atau UDF untuk memasukkan jawaban yang benar atas pertanyaan tentang alam semesta dan segala sesuatu. Loop akan terus melakukannya hingga pengguna menjawab dengan benar:

# Your User Defined Function
readinteger <- function(){
  n <- readline(prompt="Please, enter your ANSWER: ")
}

response <- as.integer(readinteger())

while (response!=42) {   
  print("Sorry, the answer to whatever the question MUST be 42");
  response <- as.integer(readinteger());
}

Sebagai awal, gunakan fungsi buatan pengguna untuk mendapatkan masukan pengguna sebelum masuk ke loop. Loop ini akan berlanjut selama jawabannya bukan 42 yang diharapkan.

Dengan kata lain, Anda melakukan ini karena jika tidak, R akan mengeluh tentang ekspresi yang hilang yang seharusnya memberikan True atau False yang diperlukan — dan faktanya, R belum mengenal ‘response’ sebelum digunakan dalam loop. Anda juga melakukan ini karena jika Anda menjawab benar pada percobaan pertama, loop tidak akan dijalankan sama sekali.

Repeat Loop

Loop repeat terletak di paling kanan bagan alir di atas. Loop ini mirip dengan loop while, tetapi dibuat sedemikian rupa sehingga blok instruksi i1 dan i2 dijalankan setidaknya sekali, apa pun hasil kondisinya.

Mengikuti penamaan di bahasa lain, loop ini bisa disebut “repeat until” untuk menekankan bahwa instruksi i1 dan i2 dijalankan sampai kondisi tetap False (F) atau, secara ekuivalen, menjadi True (T), sehingga keluar; tetapi dalam keadaan apa pun, setidaknya sekali.

Sebagai variasi dari contoh sebelumnya, Anda dapat menulis:

readinteger <- function(){
  n <- readline(prompt="Please, enter your ANSWER: ") 
}

repeat {   
  response <- as.integer(readinteger());
  if (response == 42) {
    print("Well done!");
    break
  } else print("Sorry, the answer to whatever the question MUST be 42");
}

Setelah fungsi input yang kini sudah familier, Anda memiliki loop repeat yang bloknya dijalankan setidaknya sekali dan akan berakhir kapan pun kondisi if terpenuhi.

Perhatikan bahwa Anda harus menetapkan sebuah kondisi di dalam loop yang menjadi dasar untuk keluar dengan klausa break. Klausa ini memperkenalkan konsep keluar atau menginterupsi siklus di dalam loop.

Menghentikan dan Keluar dari Loop di R

Lalu bagaimana cara keluar dari loop?

Dengan kata lain, selain dari akhir “alami” loop, yang terjadi karena Anda mencapai jumlah iterasi yang ditentukan (for) atau karena Anda memenuhi suatu kondisi (while, repeat), bisakah Anda menghentikan atau menginterupsi loop?

Dan jika bisa, bagaimana caranya?

Pernyataan break menjawab pertanyaan pertama: Anda sudah melihatnya pada contoh terakhir.

Hentikan Loop Anda dengan break

Saat interpreter R menemukan break, ia akan meneruskan kontrol ke instruksi tepat setelah akhir loop (jika ada). Dalam kasus loop bertingkat, break hanya memungkinkan untuk keluar dari loop yang paling dalam.

Berikut contohnya.

Potongan kode ini mendefinisikan matriks m x n berisi nol lalu masuk ke for loop bertingkat untuk mengisi lokasi matriks, tetapi hanya jika kedua indeks berbeda. Tujuannya adalah membuat matriks segitiga bawah, yaitu matriks yang elemennya di bawah diagonal utama tidak nol. Elemen lainnya dibiarkan seperti nilai nol awalnya.

Saat indeks sama dan dengan demikian kondisi di loop bagian dalam, yang berjalan pada indeks kolom j, terpenuhi, break dijalankan dan loop terdalam diinterupsi dengan lompatan langsung ke instruksi setelah loop dalam. Instruksi tersebut adalah instruksi print(). Kemudian, kontrol kembali ke kondisi for luar (atas baris, indeks i), yang dievaluasi lagi.

Jika indeks berbeda, penugasan dilakukan dan pencacah dinaikkan sebesar 1. Di akhir, program mencetak pencacah ctr, yang berisi jumlah elemen yang ditugaskan.

# Make a lower triangular matrix (zeroes in upper right corner)
m = 10
n = 10

# A counter to count the assignment
ctr = 0

# Create a 10 x 10 matrix with zeroes
mymat = matrix(0, m, n)

for (i in 1:m) {
    for (j in 1:n) {
        if (i == j) {
            break
        } else {
            # you assign the values only when i<>j
            mymat[i, j] = i * j
            ctr = ctr + 1
        }
    }
    print(i * j)
}

# Print how many matrix cells were assigned
print(ctr)

Catatan bahwa menaruh kurung kurawal bahkan saat tidak mutlak diperlukan mungkin terasa terlalu berhati-hati. Biasanya Anda lakukan untuk memastikan apa pun yang dibuka dengan {, juga ditutup dengan }. Jadi jika Anda melihat jumlah { atau } tidak cocok, Anda tahu ada error, meskipun sebaliknya tidak selalu benar!

Penggunaan next dalam Loop

next menghentikan suatu iterasi tertentu dan melompat ke siklus berikutnya. Faktanya, ia melompat ke evaluasi kondisi yang menaungi loop saat ini.

Di bahasa lain, Anda mungkin menemukan padanan (yang agak membingungkan) bernama “continue”, yang artinya sama: di mana pun Anda berada, setelah verifikasi kondisi, lompat ke evaluasi loop.

Contoh yang lebih sederhana untuk menjaga loop tetap berjalan sambil mengabaikan satu siklus tertentu saat kondisi terjadi adalah:

m = 20

for (k in 1:m) {
    if (!k %% 2)
        next
    print(k)
}

Kode ini mencetak semua bilangan ganjil dalam interval 1:m (di sini m=20). Dengan kata lain, semua bilangan bulat kecuali yang memiliki sisa bukan nol saat dibagi 2 (karena itu menggunakan operator modulus %%), seperti ditentukan oleh pengujian if, akan dicetak.

Bilangan yang sisanya nol tidak akan dicetak, karena program melompat ke evaluasi kondisi i in 1:m dan mengabaikan instruksi apa pun yang mungkin mengikuti. Dalam kasus ini, print(k) diabaikan.

Ringkasan Penggunaan Loop di R

  1. Usahakan menaruh sesedikit mungkin kode di dalam loop dengan mengeluarkan instruksi sebanyak mungkin. Ingat, apa pun di dalam loop akan diulang beberapa kali dan mungkin tidak diperlukan.
  2. Berhati-hatilah saat menggunakan repeat: pastikan penghentian ditetapkan secara eksplisit dengan menguji kondisi atau Anda bisa berakhir dalam loop tak berujung.
  3. Lebih baik menggunakan satu atau beberapa pemanggilan fungsi di dalam loop jika sebuah loop menjadi (terlalu) besar. Pemanggilan fungsi akan memudahkan pengguna lain mengikuti kode. Namun penggunaan for loop bertingkat untuk melakukan operasi matriks atau array kemungkinan merupakan tanda bahwa Anda belum menerapkan cara terbaik untuk bahasa berbasis matriks seperti R.
  4. Tidak disarankan “menumbuhkan” variabel atau dataset dengan melakukan assignment pada setiap iterasi. Dalam beberapa bahasa seperti Matlab, peringatan error akan diterbitkan: Anda boleh melanjutkan, tetapi disarankan mempertimbangkan alternatif. Contoh tipikal akan ditunjukkan di bagian berikutnya.

Kapan Menggunakan Loop di R

Semua ini baik-baik saja, tetapi kapan Anda seharusnya menggunakan loop di R dan kapan tidak?

Setiap kali beberapa operasi perlu diulang, loop bisa berguna.

Anda hanya perlu menentukan berapa kali atau pada kondisi apa operasi tersebut perlu dijalankan: Anda menetapkan nilai awal ke variabel loop kendali, menjalankan loop dan kemudian, setelah loop selesai, biasanya Anda melakukan sesuatu dengan hasilnya.

Tetapi kapan Anda seharusnya menggunakan loop?

Tidak bisakah Anda mereplikasi instruksi yang diinginkan sebanyak jumlah yang cukup?

Aturan praktisnya, jika Anda perlu melakukan sebuah tindakan (katakanlah) tiga kali atau lebih, maka loop akan lebih membantu. Ini membuat kode lebih ringkas, mudah dibaca, dan mudah dirawat serta Anda bisa menghemat pengetikan: misalnya Anda mendapati suatu instruksi perlu diulang sekali lebih banyak dari yang diperkirakan semula: alih-alih menulis ulang seluruh instruksi, Anda cukup mengubah nilai variabel pada kondisi uji.

Namun, sifat khas R menyarankan untuk tidak menggunakan loop sama sekali (!) bila ada alternatif.

Untungnya, ada beberapa alternatif!

R memiliki fitur yang jarang dimiliki bahasa pemrograman lain, yaitu vektorisasi.

Alternatif untuk Loop di R

Apa itu Vektorisasi?

Sesuai namanya, vektorisasi adalah operasi mengubah operasi berulang pada angka sederhana (“skalar”) menjadi operasi tunggal pada vektor atau matriks. Anda telah melihat beberapa contohnya di subbagian di atas.

Sekarang, vektor adalah struktur data elementer di R dan merupakan “entitas tunggal yang terdiri dari sekumpulan hal”, menurut manual R base.

Jadi, sekumpulan angka adalah vektor numerik.

Jika Anda menggabungkan vektor (dengan panjang yang sama), Anda memperoleh matriks. Anda dapat melakukannya secara vertikal atau horizontal, menggunakan instruksi R yang berbeda. Dengan demikian di R, matriks dipandang sebagai kumpulan vektor horizontal atau vertikal. Secara perpanjangan, Anda dapat memvektorisasi operasi berulang pada vektor.

Banyak konstruksi loop di atas dapat dibuat implisit dengan menggunakan vektorisasi.

Saya bilang “implisit”, karena loop tersebut tidak benar-benar hilang. Pada level bawah, bentuk tervektorisasi ini diterjemahkan ke kode yang akan berisi satu atau lebih loop dalam bahasa level rendah tempat bentuk tersebut diimplementasikan dan dikompilasi (Fortran, C, atau C++).

Loop ini tersembunyi dari pengguna dan biasanya lebih cepat daripada kode R eksplisit yang setara, tetapi kecuali Anda berencana mengimplementasikan fungsi R Anda sendiri menggunakan salah satu bahasa tersebut, ini sepenuhnya transparan bagi Anda.

Kasus paling dasar yang dapat Anda bayangkan adalah penjumlahan dua vektor v1 dan v2 menjadi vektor v3, yang dapat dilakukan secara elemen demi elemen dengan loop for:

v1 <- c(3,4,5)
v2 <- c(3,4,6)
v3 <- c(0,0,0)
n = length(v1)

for (i in 1:n) {
    v3[i] <- v1[i] + v2[i]
}
v3

Atau Anda juga dapat menggunakan bentuk tervektorisasi “native”:

v3 = v1 + v2
v3

Catatan bahwa kita menyebutnya “native” karena R dapat mengenali semua operator aritmetika sebagai operator atas vektor dan matriks.

Demikian pula, untuk dua matriks A dan B, alih-alih menambahkan elemen A[i,j] dan B[i,j] pada posisi yang sesuai, yang mengharuskan Anda menangani dua indeks i dan j, Anda memberi tahu R untuk melakukan hal berikut:

A <- matrix(1:6, nrow = 3, ncol = 2)
B <- matrix(c(2,4,3,1,5,7), nrow=3, ncol=2)

C= A + B
C

Dan ini memang sangat sederhana!

Penjelasan Vektorisasi di R

Mengapa vektorisasi berjalan lebih cepat, padahal jumlah operasi elementer tampaknya sama?

Ini paling baik dijelaskan dengan melihat seluk-beluk internal R, yang memerlukan tulisan terpisah, tetapi secara ringkas: pertama-tama, R adalah bahasa terinterpretasi dan karenanya, semua detail tentang definisi variabel ditangani oleh interpreter. Anda tidak perlu menyebutkan bahwa sebuah angka adalah floating point atau mengalokasikan memori menggunakan pointer di memori, misalnya.

Interpreter R “memahami” hal-hal ini dari konteks saat Anda memasukkan perintah, tetapi ia melakukannya per perintah. Karena itu ia perlu menangani definisi semacam itu setiap kali Anda menjalankan sebuah perintah, bahkan jika Anda hanya mengulanginya.

Sebaliknya, sebuah kompiler menyelesaikan semua definisi dan deklarasi saat kompilasi atas keseluruhan kode; kode tersebut diterjemahkan menjadi kode biner yang ringkas dan teroptimasi, sebelum Anda mengeksekusi apa pun. Nah, karena fungsi R ditulis dalam salah satu bahasa level lebih rendah ini, fungsi-fungsi tersebut lebih efisien.

Dalam praktiknya, jika seseorang melihat kode level rendah, ia akan menemukan pemanggilan ke C atau C++, yang biasanya diimplementasikan dalam apa yang disebut kode pembungkus (wrapper).

Kedua, dalam bahasa yang mendukung vektorisasi (seperti R atau Matlab), setiap instruksi yang menggunakan data numerik bekerja pada objek yang secara native didefinisikan sebagai vektor, bahkan jika hanya terdiri dari satu elemen. Ini adalah default saat Anda mendefinisikan, misalnya, sebuah variabel numerik tunggal: representasi internalnya di R selalu berupa vektor, meskipun hanya berisi satu angka.

Loop tetap ada di balik layar, tetapi pada level C/C++ terkompilasi yang lebih rendah dan jauh lebih cepat. Keuntungan memiliki vektor berarti definisi diselesaikan oleh interpreter sekali saja, pada seluruh vektor, tanpa memandang ukurannya, berbeda dengan loop pada skalar, di mana definisi dan alokasi perlu dilakukan per elemen, dan ini lebih lambat.

Terakhir, bekerja dengan format vektor native memungkinkan pemanfaatan rutin Aljabar Linear yang sangat efisien (seperti BLAS atau Basic Linear Algebra Subprograms), sehingga saat menjalankan instruksi tervektorisasi, R memanfaatkan rutin numerik yang efisien ini. Jadi pesannya, jika memungkinkan, proseslah seluruh struktur data dalam satu pemanggilan fungsi untuk menghindari semua operasi penyalinan yang dijalankan.

Tapi cukup dengan pengantar, mari buat contoh umum vektorisasi, lalu di subbagian berikutnya, Anda akan menyelami fungsi-fungsi tervektorisasi R yang lebih spesifik dan populer untuk menggantikan loop.

Contoh Vektorisasi di R

Kembali ke gagasan “menumbuhkan data”, cara yang biasanya tidak efisien untuk “memperbarui” sebuah data frame.

Pertama, Anda membuat matriks m x n dengan replicate(m, rnorm(n)) dengan m=10 vektor kolom yang masing-masing memiliki n=10 elemen, dibentuk dengan rnorm(n), yang membuat angka acak berdistribusi normal.

Lalu Anda mengubahnya menjadi data frame (jadi 10 observasi dari 10 variabel) dan melakukan operasi aljabar pada setiap elemen menggunakan for loop bertingkat: pada tiap iterasi, sebuah fungsi sinus menambah setiap elemen yang dirujuk oleh dua indeks.

Contoh berikut memang agak artifisial, tetapi dapat mewakili penambahan sinyal ke beberapa noise acak:

# This is a bad loop with 'growing' data
set.seed(42)
m = 10
n = 10

# Create matrix of normal random numbers
mymat <- replicate(m, rnorm(n))

# Transform into data frame
mydframe <- data.frame(mymat)

for (i in 1:m) {
  for (j in 1:n) {
    mydframe[i, j] <- mydframe[i, j] + 10 * sin(0.75 * pi)
    print(mydframe)
  }
}

Di sini, sebagian besar waktu eksekusi terdiri dari penyalinan dan pengelolaan loop.

Mari lihat seperti apa solusi tervektorisasi:

set.seed(42)
m = 10
n = 10
mymat <- replicate(m, rnorm(n))
mydframe <- data.frame(mymat)
mydframe <- mydframe + 10 * sin(0.75 * pi)
mydframe

Ini terlihat lebih sederhana: baris terakhir menggantikan for loop bertingkat. Catatan penggunaan set.seed() untuk memastikan kedua implementasi memberikan hasil yang persis sama.

Sekarang mari kuantifikasi waktu eksekusi untuk kedua solusi.

Anda dapat melakukannya dengan menggunakan perintah sistem R, seperti system.time() yang dapat diberi potongan kode seperti ini:

Tips: cukup letakkan kode yang ingin Anda evaluasi di dalam tanda kurung fungsi system.time().

# Insert `system.time()` to measure loop execution
for (i in 1:m) {
  for (j in 1:n) {
    mydframe[i, j] <- mydframe[i, j] + 10 * sin(0.75 * pi)
  }
}

# Add `system.time()` to measure vectorized execution
mydframe <- mydframe + 10 * sin(0.75 * pi) 

Pada potongan kode di atas, Anda melakukan tugas memilih m dan n, pembuatan matriks dan transformasinya menjadi data frame hanya sekali di awal, lalu mengevaluasi potongan for melawan “satu baris” versi tervektorisasi dengan dua pemanggilan terpisah ke system.time().

Anda melihat bahwa bahkan dengan pengaturan minimal m=n=10 versi tervektorisasi 7 kali lebih cepat, meskipun untuk nilai serendah itu, perbedaannya nyaris tidak penting bagi pengguna.

Perbedaan menjadi nyata (pada skala manusia) jika Anda menaruh m=n=100, sementara peningkatan ke 1000 membuat for loop tampak menggantung selama beberapa puluh detik, sedangkan bentuk tervektorisasi masih berjalan sekejap mata.

Untuk m=n=10000 for loop menggantung lebih dari satu menit sementara bentuk tervektorisasi membutuhkan 2,54 detik. Tentu saja, ukuran ini sebaiknya disikapi ringan dan akan bergantung pada konfigurasi perangkat keras dan perangkat lunak, sebaiknya hindari membebani laptop Anda dengan puluhan tab browser terbuka dan beberapa aplikasi berjalan di latar belakang; tetapi ukuran ini ilustratif terhadap perbedaannya.

Secara adil, peningkatan m dan n juga sangat memengaruhi pembuatan matriks seperti yang dapat Anda lihat dengan mudah dengan menempatkan satu lagi pemanggilan system.time() di sekitar fungsi replikasi.

Anda dipersilakan untuk bereksperimen dengan m dan n guna melihat bagaimana waktu eksekusi berubah, dengan memplot waktu eksekusi sebagai fungsi dari produk m x n. Ini adalah indikator yang relevan, karena mengekspresikan dimensi matriks yang dibuat. Dengan demikian juga mengkuantifikasi jumlah iterasi yang diperlukan untuk menyelesaikan tugas melalui for loop yang nset-ed.

Jadi ini adalah contoh vektorisasi. Namun ada banyak lagi. Dalam R News, buletin untuk proyek R pada halaman 46, terdapat fungsi yang sangat efisien untuk menghitung jumlah dan rerata pada dimensi tertentu dalam array atau matriks, seperti: rowSums(), colSums(), rowMeans(), dan colMeans().

Selain itu, buletin juga menyebutkan bahwa “...fungsi dalam keluarga ‘apply’, bernama [s,l,m,t]apply, disediakan untuk menerapkan fungsi lain ke elemen/dimensi objek. Fungsi ‘apply’ ini menyediakan sintaks ringkas untuk tugas yang kadang cukup kompleks yang lebih mudah dibaca dan lebih cepat daripada loop yang ditulis kurang baik.”.

Keluarga apply: sekadar loop tersembunyi?

Keluarga fungsi apply yang sangat kaya dan kuat terdiri dari fungsi-fungsi yang secara intrinsik tervektorisasi. Jika sekilas fungsi-fungsi ini tampak tidak mengandung loop, fitur ini menjadi nyata ketika Anda menengok ke balik layar.

Perintah apply atau tepatnya keluarga perintah ini, termasuk dalam paket R base. Ia diisi oleh sejumlah fungsi ([s,l,m,r, t,v]apply) untuk memanipulasi potongan data dalam bentuk matriks atau array secara repetitif, memungkinkan melintasi data dan menghindari penggunaan eksplisit konstruksi loop. Fungsi-fungsi ini bekerja pada matriks atau array masukan dan menerapkan fungsi bernama pilihan dengan satu atau beberapa argumen opsional.

Catatan itulah sebabnya fungsi-fungsi tersebut termasuk dalam golongan ‘functionals’ (sebagaimana di halaman advanced R Hadley Wickham).

Fungsi yang dipanggil bisa berupa fungsi agregasi, seperti mean sederhana, atau fungsi transformasi atau subsetting lainnya.

Perlu dicatat bahwa penerapan fungsi-fungsi ini tidak selalu menghasilkan eksekusi yang lebih cepat: perbedaannya tidak besar; yang lebih penting adalah menghindari penulisan loop yang merepotkan, sehingga mengurangi peluang terjadinya error.

Fungsi dalam keluarga ini adalah: apply(), sapply(), lapply(), mapply(), rapply(), tapply(), vapply().

Lalu kapan dan bagaimana Anda harus menggunakannya?

Perlu dicatat bahwa paket seperti plyr mencakup fungsionalitas keluarga ini; meskipun mengingat semuanya tanpa merujuk dokumentasi resmi terasa sulit, fungsi-fungsi ini tetap menjadi dasar dari kombinasi yang lebih kompleks dan bermanfaat.

Tiga yang pertama paling sering digunakan:

  1. apply()

Anda ingin menerapkan suatu fungsi pada baris (indeks “1”) atau kolom (indeks “2”) dari sebuah matriks. Lihat halaman ini untuk informasi lebih lanjut.

  1. lapply()

Anda ingin menerapkan suatu fungsi pada setiap elemen list dan memperoleh list sebagai hasilnya (menjelaskan huruf “l” pada nama fungsi). Baca tentang fungsi ini di dokumentasi R.

  1. sapply()

Anda ingin menerapkan suatu fungsi pada setiap elemen list tetapi menginginkan vektor alih-alih list sebagai hasilnya. Perlu tahu lebih banyak? Kunjungi halaman dokumentasi R.

Fungsi terkait adalah sweep(), by() dan aggregate() dan sesekali digunakan bersama elemen keluarga apply().

Saya membatasi pembahasan posting blog ini pada fungsi apply() (pembahasan lebih luas mungkin menjadi fokus tulisan mendatang).

Diberikan matriks M, pemanggilan apply(M,1,fun) atau apply(M, 2,fun) akan menerapkan fungsi fun yang ditentukan pada baris M, jika 1 ditentukan; atau pada kolom M, jika 2 ditentukan. Argumen numerik ini disebut “margin” dan terbatas pada nilai 1 dan 2 karena fungsi bekerja pada matriks. Namun, Anda juga bisa memiliki array hingga 8 dimensi.

Fungsinya bisa berupa fungsi R apa pun yang valid, dan bisa juga berupa User Defined Function (UDF), bahkan dikodekan di dalam apply(), yang cukup praktis.

apply(): sebuah contoh

# define matrix `mymat` by replicating the sequence `1:5` for `4` times and transforming into a matrix
mymat <- matrix(rep(seq(5), 4), ncol = 5)

# `mymat` sum on rows
apply(mymat, 1, sum)

# `mymat` sum on columns
apply(mymat, 2, sum)

# With user defined function within the apply that adds any number `y` to the sum of the row
# `y` is set at `4.5`
apply(mymat, 1, function(x, y)
  sum(x) + y, y = 4.5)

# Or produce a summary column wise for each column
apply(mymat, 2, function(x, y)
  summary(mymat))

Anda sering menggunakan data frame: dalam kasus ini, Anda harus memastikan datanya memiliki tipe yang sama, jika tidak, konversi tipe data secara paksa dapat terjadi, yang kemungkinan besar bukan yang Anda inginkan. Misalnya, dalam data frame campuran teks dan angka, data numerik akan dikonversi menjadi string atau karakter.

Pertimbangan Akhir tentang Penggunaan dan Alternatif Loop di R

Sekarang, perjalanan ini membawa kita dari konstruksi loop fundamental yang digunakan dalam pemrograman ke gagasan (dasar) tentang vektorisasi dan ke contoh penggunaan salah satu fungsi keluarga apply(), yang sering muncul di R.

Dari sisi alur kendali kode, Anda hanya berurusan dengan loop: for, while, repeat dan cara menginterupsi serta keluar darinya.

Karena subbagian terakhir memberi petunjuk bahwa loop di R sebaiknya dihindari, Anda mungkin bertanya mengapa harus mempelajarinya.

Menurut saya, Anda perlu mempelajari struktur pemrograman ini karena:

  1. Kemungkinan R bukan satu-satunya bahasa Anda dalam data science atau bidang lain, dan memahami konstruksi umum seperti loop adalah hal berguna untuk dimasukkan ke dalam tas keterampilan Anda. Sintaks loop mungkin berbeda tergantung bahasanya, tetapi setelah Anda menguasainya di satu bahasa, Anda akan dengan mudah menerapkannya ke bahasa lain yang Anda temui.
  2. Ekosistem R sangat besar dan sangat sulit, jika bukan tidak mungkin, untuk menyadari semua fungsi R yang ada. Ada banyak cara untuk melakukan sesuatu, beberapa lebih efisien atau elegan daripada yang lain dan kurva belajar Anda akan bertahap; Saat menggunakannya, Anda akan mulai bertanya pada diri sendiri tentang cara yang lebih efisien untuk melakukan sesuatu dan pada akhirnya Anda akan menemukan fungsi yang belum pernah Anda dengar. Pada saat Anda membaca ini, beberapa library baru akan dikembangkan, yang lain dirilis, dan peluang untuk mengetahui semuanya kecil, kecuali Anda menghabiskan seluruh waktu sebagai spesialis R.
  3. Terakhir, setidaknya saat tidak berurusan dengan dataset berdimensi sangat tinggi, solusi loop akan mudah dikodekan dan dibaca. Dan barangkali, sebagai data scientist, Anda diminta membuat prototipe pekerjaan sekali jalan yang sekadar berfungsi. Mungkin, Anda tidak tertarik pada cara-cara canggih atau elegan untuk mendapatkan hasil. Mungkin, dalam alur kerja analisis data, Anda hanya perlu menunjukkan keahlian domain dan fokus pada konten. Orang lain, kemungkinan spesialis back-end, akan menanganinya di fase produksi (dan mungkin ia akan mengodekannya dalam bahasa yang berbeda!)

Jika for loop di R tidak lagi menjadi tantangan bagi Anda setelah membaca tutorial ini, Anda bisa mempertimbangkan mengikuti kursus Intermediate R dari DataCamp. Kursus ini akan memperkuat pengetahuan Anda tentang topik di Intermediate R dengan serangkaian latihan baru yang menyenangkan. Jika, bagaimanapun, loop tidak lagi menyimpan rahasia bagi Anda, kursus Writing Functions in R dari DataCamp, yang diajarkan oleh Hadley dan Charlotte Wickham, bisa menarik bagi Anda. Juga, lihat tutorial For Loops in R.

Jalankan dan edit kode dari Tutorial ini secara online

Jalankan kode

FAQ Loop di R

Apa itu loop di R dan mengapa berguna?

Loop adalah cara untuk mengulang blok kode beberapa kali. Ini berguna saat Anda ingin melakukan tindakan yang sama pada banyak titik data atau objek, atau saat Anda ingin mengulangi tindakan hingga kondisi tertentu terpenuhi.

Apa saja jenis loop yang berbeda di R?

Ada dua jenis utama loop di R: for loop dan while loop.

  • For loop mengulang blok kode untuk setiap item dalam sebuah list atau urutan. Misalnya, Anda dapat menggunakan for loop untuk mencetak semua elemen dari sebuah vektor, atau menerapkan fungsi ke setiap elemen dari sebuah list.
  • While loop mengulang blok kode selama kondisi tertentu bernilai benar. Misalnya, Anda dapat menggunakan while loop untuk terus meminta masukan pengguna hingga mereka memasukkan respons yang valid.

Bagaimana cara menghentikan loop di R?

Untuk menghentikan loop di R, Anda dapat menggunakan pernyataan break. Ini akan segera keluar dari loop dan melanjutkan dengan sisa kode.

Bagaimana cara melompati ke iterasi berikutnya dalam loop di R?

Untuk melompati ke iterasi berikutnya dalam loop di R, Anda dapat menggunakan pernyataan next. Ini akan melewati sisa iterasi saat ini dan lanjut ke berikutnya.

Bisakah saya menaruh loop di dalam loop lain di R?

Ya, Anda dapat menempatkan loop di dalam loop lain di R. Ini disebut "loop bertingkat" (nesting). Misalnya, Anda dapat menggunakan for loop di dalam for loop lain untuk mengiterasi elemen-elemen dari sebuah matriks.

Topik
R
Data Science

Pelajari lebih lanjut tentang R

Kursus

Pengantar Penulisan Fungsi di R

4 jam
53.9K
Tingkatkan keterampilan R Anda dengan belajar menulis fungsi yang efisien dan dapat digunakan kembali.
Lihat DetailRight Arrow
Mulai Kursus
Lihat SelengkapnyaRight Arrow
Terkait

blogs

Tutorial Korelasi di R

Dapatkan pengenalan dasar-dasar korelasi di R: pelajari lebih lanjut tentang koefisien korelasi, matriks korelasi, plotting korelasi, dan sebagainya.
David Woods's photo

David Woods

13 mnt

blogs

Spaghetti Plot dan Jalur Badai

Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Hugo Bowne-Anderson's photo

Hugo Bowne-Anderson

13 mnt

blogs

12 Alternatif ChatGPT Terbaik yang Bisa Anda Coba pada 2026

Artikel ini menyajikan daftar alternatif ChatGPT yang akan meningkatkan produktivitas Anda.
Javier Canales Luna's photo

Javier Canales Luna

14 mnt

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Dario Radečić's photo

Dario Radečić

15 mnt

Lihat SelengkapnyaLihat Selengkapnya