New*_*tat 5 performance loops r vectorization
几乎只要你完成了对R的介绍,你可能已经学习了for循环的语法,你被告知要避免R中的循环!
R是一种矢量化语言,所以你被告知永远不要做类似的事情
x = 1:10
y = 2:11
z = rep(NA, 10)
for i in 1:10{
z[i] = x[i] + y[i]
}
Run Code Online (Sandbox Code Playgroud)
而是做
z = x + y
Run Code Online (Sandbox Code Playgroud)
您还被告知使用*ply函数族来进行迭代循环.
我的问题是,除了潜在的代码可读性场景之外,是否还有很好的时间用于R中的循环?
高级 R提到了循环的三种情况:就地修改、递归函数和 while 循环。由于您要求for循环,以下是前两种情况下的内容:
就地修改
如果您需要修改现有数据框的一部分,通常最好使用 for 循环。例如,以下代码通过将函数列表的名称与数据框中的变量名称进行匹配来执行逐个变量的转换。
trans <- list(
disp = function(x) x * 0.0163871,
am = function(x) factor(x, levels = c("auto", "manual"))
)
for(var in names(trans)) {
mtcars[[var]] <- trans[[var]](mtcars[[var]])
}
Run Code Online (Sandbox Code Playgroud)
我们通常不会使用 lapply() 直接替换这个循环,但这是可能的。
递归关系
当元素之间的关系不独立或递归定义时,很难将 for 循环转换为函数式。例如,指数平滑的工作原理是取当前和先前数据点的加权平均值。下面的 exps() 函数使用 for 循环实现指数平滑。
exps <- function(x, alpha) {
s <- numeric(length(x) + 1)
for (i in seq_along(s)) {
if (i == 1) {
s[i] <- x[i]
} else {
s[i] <- alpha * x[i - 1] + (1 - alpha) * s[i - 1]
}
}
s
}
x <- runif(6)
exps(x, 0.5)
#> [1] 0.6622163 0.6622163 0.4758159 0.2703593 0.1896377 0.5506731 0.7300305
Run Code Online (Sandbox Code Playgroud)
我们无法消除 for 循环,因为我们见过的函数都不允许位置 i 的输出依赖于位置 i - 1 的输入和输出。
创建多页 pdf 图表。或者实际上任何每次迭代都需要很长时间的事情,就像绘图的生成一样。如果循环不是瓶颈,那么对我来说这种方式几乎总是更具可读性,所以我就这样做。
pdf("file.pdf", onefile=TRUE)
for(var in unique(df$some_var)){
p <- ggplot(df[df$some_var==var, ], aes(x=x, y=y)) + geom_line()
print(p)
}
dev.off()
Run Code Online (Sandbox Code Playgroud)