Advanced 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]])
}
我们通常不会直接使用lapply()来替换这个循环,但这是可能的。
递归关系
当元素之间的关系不独立或通过递归定义时,很难将for循环转化为函数式。例如,指数平滑通过对当前和前一个数据点加权平均来工作。下面的exp()函数使用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)
我们无法消除for循环,因为我们所见过的函数式编程方法都不允许位置i处的输出依赖于位置i-1处的输入和输出。
for
循环。虽然Reduce
具有类似的潜力,但我认为for
循环更好。 - akrundata.table
或利用Rcpp
的威力。 - Roman Luštrik