R 中的 For 循环以及列表和矩阵的示例

⚡ 智能摘要

R 语言中的 for 循环会对序列中的每个元素执行一次代码块,无论该序列是向量、列表还是矩阵。本教程将逐一介绍这些类型,并展示何时使用向量化代码更为合适。

  • 🔁 核心语法: for (i in vector) { expression } 依次将每个元素赋值给 i 并运行表达式主体。
  • 📋 任何对象: 相同的语法可以遍历向量、列表、数据框列集或矩阵的行。
  • 🧮 嵌套循环: 矩阵需要两个循环,外层循环用于行,内层循环用于列。
  • 🛑 流量控制: break 会完全退出循环,而 next 只会跳过当前元素。
  • 先进行向量化: 内置的向量化操作和 apply 系列函数比显式循环更快、更简洁。
  • ⚠️ 安全序列: 请使用 seq_along(x) 而不是 1:length(x),因为当对象为空时,后者会运行异常。

R 语言中的 for 循环列表矩阵

A for循环 对序列中的每个元素重复执行一次代码块。该序列可以是向量、列表、数据框、矩阵或 R 可以迭代的任何其他对象。R 区分大小写,因此关键字始终为小写。 HPMC胶囊当正文跨越多行时,需要使用花括号。

R语言中的for循环语法

for (i in vector) {
    Exp
}

在这里,

R 将循环遍历向量中的所有变量并执行 exp 中写的计算。

R 中的 For 循环
R 中的 For 循环

我们来看几个例子。

R 中的 For 循环示例 1:我们迭代向量的所有元素并打印当前值。

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

输出:

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

R 中的 For 循环示例 2将 1 到 4 之间的每个整数平方,并将结果存储在一个列表中。

# 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)

输出:

## [1]   1  4 9 16

for 循环在机器学习工作中非常有用。调整正则化参数意味着测试许多候选值并保持……ping 找到使损失函数最小化的函数,而 for 循环是扫描该范围的直接方法。

如何在 for 循环中使用 break 和 next

两个关键字会中断 for 循环的正常顺序。

  • 打破 立即退出循环并跳过所有剩余元素。
  • 下页 仅放弃当前元素,并继续处理下一个元素。
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)
}

在嵌套循环中,`break` 和 `next` 语句仅作用于包含它们的最内层循环。要在矩阵示例中保持两个循环都有效,需要设置一个标志变量,并在外层循环中也对其进行测试。

对索引使用 seq_along()。 编写 `for (i in 1:length(x))` 看起来无害,但对空对象会失败,因为 `1:0` 会生成序列 `1, 0`,导致循环执行两次。而 `seq_along(x)` 返回的是一个空序列,因此循环被正确地跳过了。

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

遍历列表的 for 循环

厕所ping 对列表进行操作与 loo 完全相同。ping 是一个向量,但每个元素可以包含不同的类型:

# 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)
}

输出:

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

遍历矩阵的 for 循环

矩阵有两个维度,行和列,因此遍历每个单元格需要两个嵌套的 for 循环:一个外层循环用于行,一个内层循环用于列。

# 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]))  

输出:

## [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" 

R语言中遍历数据框的for循环

数据框是列的列表,因此普通的 for 循环遍历的是列而不是行。这通常正是你想要的:

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')
}

注意双括号。df[[col]] 例如tracts 将列作为向量,而 df[col] 返回一个 mean() 无法处理的单列数据框。

厕所ping 超过行。 逐行迭代是可行的,但速度很慢,因为 R 每次迭代都会复制该行:

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

对于超过几千行的数据,建议使用 rowSums(df)、apply(df, 1, sum) 或 dplyr 函数。 group_by() 和 summarise() 管道,所有这些管道都执行相同的工作,而无需复制。

R语言中的for循环与向量化

R 是一种向量化语言:它的大多数运算符和函数在编译后的 C 代码中已经可以一次性作用于整个向量。显式地使用循环逐个元素地重复向量化操作,既耗时又费力。

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

# Vectorized version, same result
squares <- (1:4)^2
任务 循环 向量化等效物
逐元素运算 对于每个元素 x * 2,x + y,x²
对每列应用一个函数 对于所有名称(df) sapply(df, mean)
每行应用一个函数 对于 seq_len(nrow(df)) apply(df, 1, sum)
生成结果列表 for with list[[i]] <- … lapply(v, f)
条件重编码 以及 if 和 else ifelse(cond, a, b)

循环仍然是正确答案的时候。 当每次迭代都依赖于前一次迭代的结果时,当调用外部服务或写入文件时,或者当处理小对象时,清晰度比速度更重要时,请保留 for 循环。

如果必须循环,请预先分配内存。 在循环中不断增大对象大小会迫使 R 在每次循环时都复制该对象。请先创建完整大小的对象:

# 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

R 语言中的 for 循环:快速参考

本教程中使用的所有结构如下所示:

目的 Code
遍历向量
for (i in v) { print(i) }
安全地遍历索引。
for (i in seq_along(v)) { print(v[i]) }
遍历列表
for (p in my_list) { print(p) }
遍历数据框列
for (col in names(df)) { print(mean(df[[col]])) }
遍历矩阵
for (r in 1:nrow(m)) for (c in 1:ncol(m)) print(m[r, c])
提前退出循环
if (condition) break
跳过一次迭代
if (condition) next
预先分配输出
out <- numeric(n)

常见问题

当 x 为空时,1:length(x) 返回序列 1, 0,循环会对不存在的元素执行两次。seq_along(x) 返回一个空序列,因此循环会被正确地跳过。

循环本身不是问题,问题在于循环内部对象的大小增长,因为 R 每次循环都会复制整个对象。预先分配结果空间,或者使用向量化函数,就能基本消除这种性能差距。

列。数据框是一个列列表,因此每次迭代都会返回一整列。如果需要遍历行,请显式使用 `seq_len(nrow(df))`。

for 循环用于驱动超参数扫描、交叉验证折叠和训练轮数。每个步骤都有已知的迭代次数,而这正是 for 循环结构的设计初衷。

是的。AI 助手可以将大多数逐元素循环转换为向量化或应用族等价形式。在替换原始代码之前,请使用 `identical()` 函数比较两种版本的输出结果。

总结一下这篇文章: