Vòng lặp For trong R với các ví dụ về Danh sách và Ma trận

⚡ Tóm tắt thông minh

Vòng lặp `for` trong R thực thi một khối mã một lần cho mỗi phần tử của một chuỗi, cho dù chuỗi đó là một vectơ, một danh sách hay một ma trận. Hướng dẫn này sẽ lặp qua từng trường hợp và chỉ ra khi nào mã được vector hóa là lựa chọn tốt hơn.

  • 🔁 Cú pháp cốt lõi: vòng lặp for (i in vector) { expression } lần lượt gán từng phần tử cho i và chạy phần thân.
  • 📋 Bất kỳ đối tượng nào: Cú pháp này có thể được sử dụng để duyệt qua một vectơ, một danh sách, một tập hợp cột của khung dữ liệu hoặc các hàng của một ma trận.
  • 🧮 Vòng lặp lồng nhau: Ma trận cần hai vòng lặp, một vòng lặp ngoài cho hàng và một vòng lặp trong cho cột.
  • 🛑 Kiểm soát lưu lượng: Lệnh break thoát khỏi vòng lặp hoàn toàn, còn lệnh next chỉ bỏ qua phần tử hiện tại.
  • ⚡ Ưu tiên vector hóa: Các phép toán vector hóa tích hợp sẵn và nhóm hàm apply nhanh hơn và ngắn gọn hơn so với vòng lặp tường minh.
  • ⚠️ Trình tự an toàn: Hãy sử dụng seq_along(x) thay vì 1:length(x), vì nó hoạt động không đúng cách khi đối tượng trống.

Vòng lặp for trong ma trận danh sách R

A vòng lặp for Lặp lại một khối mã một lần cho mỗi phần tử của một chuỗi. Chuỗi đó có thể là một vectơ, một danh sách, một khung dữ liệu, một ma trận hoặc bất kỳ đối tượng nào khác mà R có thể lặp qua. R phân biệt chữ hoa chữ thường, vì vậy từ khóa luôn được viết thường. chovà dấu ngoặc nhọn là bắt buộc khi nội dung trải dài hơn một dòng.

Cú pháp vòng lặp for trong R

for (i in vector) {
    Exp
}

Ở đây,

R sẽ lặp qua tất cả các biến trong vector và thực hiện phép tính được viết bên trong exp.

Vòng lặp trong R
Vòng lặp trong R

Hãy xem một vài ví dụ.

Vòng lặp For trong R Ví dụ 1: Chúng ta lặp lại tất cả các phần tử của một vectơ và in ra giá trị hiện tại.

# Create fruit vector
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')
# Create the for statement
for ( i in fruit){ 
 print(i)
}

Đầu ra:

## [1] "Apple"
## [1] "Orange"
## [1] "Passion fruit"
## [1] "Banana"

Vòng lặp For trong R Ví dụ 2Bình phương mọi số nguyên từ 1 đến 4 và lưu kết quả vào một danh sách.

# Create an empty list
list <- c()
# Create a for statement to populate the list
for (i in seq(1, 4, by=1)) {
  list[[i]] <- i*i
}
print(list)

Đầu ra:

## [1]   1  4 9 16

Vòng lặp for rất hữu ích trong công việc học máy. Việc điều chỉnh tham số điều chuẩn có nghĩa là phải kiểm tra nhiều giá trị ứng cử viên và giữ cho...ping Phương pháp tối thiểu hóa hàm mất mát là sử dụng vòng lặp for, và đây là cách đơn giản nhất để quét phạm vi đó.

Cách sử dụng break và next trong vòng lặp for

Hai từ khóa làm gián đoạn trình tự hoạt động bình thường của vòng lặp for.

  • phá vỡ Thoát khỏi vòng lặp ngay lập tức và bỏ qua tất cả các phần tử còn lại.
  • tiếp theo Chỉ bỏ qua phần tử hiện tại và chuyển sang phần tử tiếp theo.
fruit <- c('Apple', 'Orange', 'Passion fruit', 'Banana')

# break: stop at the first match
for (i in fruit) {
    if (i == 'Passion fruit') {
        print('Found it, stopping here')
        break
    }
    print(i)
}

# next: skip one element and carry on
for (i in fruit) {
    if (i == 'Orange') next
    print(i)
}

Trong các vòng lặp lồng nhau, lệnh break và next chỉ tác động lên vòng lặp trong cùng chứa chúng. Để giữ nguyên cả hai vòng lặp trong ví dụ ma trận, hãy đặt một biến cờ và kiểm tra nó trong vòng lặp ngoài cùng.

Sử dụng seq_along() cho chỉ mục. Việc viết vòng lặp for (i in 1:length(x)) trông có vẻ vô hại nhưng sẽ gặp lỗi với một đối tượng rỗng, vì 1:0 tạo ra chuỗi 1, 0 và vòng lặp chạy hai lần. Hàm seq_along(x) trả về một chuỗi rỗng, do đó vòng lặp được bỏ qua một cách chính xác:

for (i in seq_along(fruit)) {
    cat(i, fruit[i], '\n')
}

Vòng lặp for trên một danh sách

Looping Việc liệt kê hoạt động chính xác như loo.ping trên một vectơ, ngoại trừ mỗi phần tử có thể chứa một kiểu dữ liệu khác nhau:

# Create a list with three vectors
fruit <- list(Basket = c('Apple', 'Orange', 'Passion fruit', 'Banana'), 
Money = c(10, 12, 15), purchase = FALSE)
for (p  in fruit) 
{ 
	print(p)
}

Đầu ra:

## [1] "Apple" "Orange" "Passion fruit" "Banana"       
## [1] 10 12 15
## [1] FALSE

Vòng lặp for trên ma trận

Ma trận có hai chiều, hàng và cột, vì vậy việc lặp qua từng ô cần hai vòng lặp for lồng nhau: một vòng lặp bên ngoài cho hàng và một vòng lặp bên trong cho cột.

# Create a matrix
mat <- matrix(data = seq(10, 20, by=1), nrow = 6, ncol =2)
# Create the loop with r and c to iterate over the matrix
for (r in 1:nrow(mat))   
    for (c in 1:ncol(mat))  
         print(paste("Row", r, "and column",c, "have values of", mat[r,c]))  

Đầu ra:

## [1] "Row 1 and column 1 have values of 10"
## [1] "Row 1 and column 2 have values of 16"
## [1] "Row 2 and column 1 have values of 11"
## [1] "Row 2 and column 2 have values of 17"
## [1] "Row 3 and column 1 have values of 12"
## [1] "Row 3 and column 2 have values of 18"
## [1] "Row 4 and column 1 have values of 13"
## [1] "Row 4 and column 2 have values of 19"
## [1] "Row 5 and column 1 have values of 14"
## [1] "Row 5 and column 2 have values of 20"
## [1] "Row 6 and column 1 have values of 15"
## [1] "Row 6 and column 2 have values of 10" 

Vòng lặp for trên một DataFrame trong R

DataFrame là một danh sách các cột, vì vậy vòng lặp for thông thường sẽ duyệt qua các cột chứ không phải các hàng của nó. Đó thường là điều bạn muốn:

df <- data.frame(a = 1:5, b = 6:10, c = 11:15)

# Loop over the columns
for (col in names(df)) {
    cat(col, 'has mean', mean(df[[col]]), '\n')
}

Lưu ý dấu ngoặc kép. df[[col]] extracts cột dưới dạng một vectơ, trong khi df[col] trả về một khung dữ liệu một cột mà mean() không thể xử lý.

Looping trên các hàng. Việc lặp từng hàng là khả thi nhưng chậm, vì R sao chép hàng đó trong mỗi lần lặp:

for (r in seq_len(nrow(df))) {
    cat('Row', r, 'sums to', sum(df[r, ]), '\n')
}

Đối với bất kỳ số lượng hàng nào vượt quá vài nghìn hàng, hãy ưu tiên sử dụng rowSums(df), apply(df, 1, sum) hoặc dplyr. group_by() và summarise() các quy trình, tất cả đều thực hiện cùng một công việc mà không cần sao chép.

So sánh vòng lặp for và vector hóa trong R

R là một ngôn ngữ lập trình hướng đối tượng (vectorized): hầu hết các toán tử và hàm của nó đều tác động đồng thời lên toàn bộ vector trong mã C đã biên dịch. Một vòng lặp tường minh lặp lại thao tác hướng đối tượng từng phần tử một sẽ dài hơn và chậm hơn.

# Loop version
squares <- c()
for (i in 1:4) {
    squares[i] <- i * i
}

# Vectorized version, same result
squares <- (1:4)^2
Nhiệm vụ Vòng lặp Tương đương dạng vector
phép toán từng phần tử cho mỗi phần tử x * 2, x + y, x^2
Áp dụng một hàm cho mỗi cột cho các tên (df) áp dụng(df, trung bình)
Áp dụng một hàm cho mỗi hàng cho trên seq_len(nrow(df)) áp dụng(df, 1, sum)
Lập danh sách kết quả với danh sách[[i]] <- … lapply(v, f)
Mã hóa lại có điều kiện với điều kiện if và else ifelse(cond, a, b)

Khi vòng lặp vẫn là giải pháp đúng. Hãy giữ lại vòng lặp for khi mỗi lần lặp phụ thuộc vào kết quả trước đó, khi bạn gọi một dịch vụ bên ngoài hoặc ghi tệp, hoặc khi sự rõ ràng quan trọng hơn tốc độ đối với một đối tượng nhỏ.

Nếu bắt buộc phải sử dụng vòng lặp, hãy cấp phát bộ nhớ trước. Việc mở rộng một đối tượng bên trong vòng lặp buộc R phải sao chép nó trong mỗi lần lặp. Hãy tạo đối tượng ở kích thước đầy đủ trước:

# Slow: the vector is reallocated on every pass
out <- c()
for (i in 1:1000) out[i] <- i^2

# Fast: allocated once
out <- numeric(1000)
for (i in 1:1000) out[i] <- i^2

Vòng lặp For trong R: Hướng dẫn nhanh

Tất cả các cấu trúc được sử dụng trong hướng dẫn này đều được liệt kê bên dưới:

Mục tiêu Code
Lặp qua một vectơ
for (i in v) { print(i) }
Lặp qua các chỉ mục một cách an toàn
for (i in seq_along(v)) { print(v[i]) }
Lặp qua một danh sách
for (p in my_list) { print(p) }
Lặp qua các cột của khung dữ liệu
for (col in names(df)) { print(mean(df[[col]])) }
Lặp qua ma trận
for (r in 1:nrow(m)) for (c in 1:ncol(m)) print(m[r, c])
Thoát khỏi vòng lặp sớm
if (condition) break
Bỏ qua một lần lặp
if (condition) next
Phân bổ trước đầu ra
out <- numeric(n)

Câu Hỏi Thường Gặp

Khi x rỗng, 1:length(x) trả về chuỗi 1, 0 và vòng lặp chạy hai lần trên các phần tử không tồn tại. seq_along(x) trả về một chuỗi rỗng, do đó vòng lặp được bỏ qua một cách chính xác.

Bản thân vòng lặp không phải là vấn đề. Vấn đề nằm ở việc mở rộng một đối tượng bên trong vòng lặp, bởi vì R sao chép toàn bộ đối tượng trong mỗi lần lặp. Hãy cấp phát trước kết quả hoặc sử dụng hàm vector hóa, và vấn đề sẽ được giải quyết phần lớn.

Các cột. Một data frame là một danh sách các cột, vì vậy mỗi lần lặp sẽ trả về cho bạn một cột hoàn chỉnh. Hãy sử dụng seq_len(nrow(df)) một cách rõ ràng nếu bạn cần duyệt qua các hàng.

Vòng lặp for điều khiển việc quét siêu tham số, các fold kiểm định chéo và các epoch huấn luyện. Mỗi thao tác này đều có số lần lặp xác định, và đó chính xác là mục đích thiết kế của cấu trúc for.

Đúng vậy. Trợ lý AI có thể chuyển đổi hầu hết các vòng lặp từng phần tử thành các dạng tương đương được vector hóa hoặc áp dụng. Hãy so sánh kết quả đầu ra của cả hai phiên bản với cùng một hàm () trước khi thay thế phiên bản gốc.

Tóm tắt bài viết này với: