我一直在网上看到很多关于如何不建议循环的数据科学家的评论.但是,我最近发现自己处于使用一个有用的情况.我想知道以下过程是否有更好的替代方案(为什么替代方案会更好):
我需要运行一系列重复测量ANOVA,并且与您在下面看到的可重现示例类似地解决问题.
[我知道有关于运行多个ANOVA模型的其他问题,并且还有其他选项可用于这些类型的分析,但是现在我只想听听for循环的使用]
作为一个例子,四个重复测量ANOVA模型 - 四个因变量,每个变量分别在三个时间测量:
set.seed(1976)
code <- seq(1:60)
time <- rep(c(0,1,2), each = 20)
DV1 <- c(rnorm(20, 10, 2), rnorm(20, 10, 2), rnorm(20, 14, 2))
DV2 <- c(rnorm(20, 10, 2), rnorm(20, 10, 2), rnorm(20, 10, 2))
DV3 <- c(rnorm(20, 10, 2), rnorm(20, 10, 2), rnorm(20, 8, 2))
DV4 <- c(rnorm(20, 10, 2), rnorm(20, 10, 2), rnorm(20, 10, 2))
dat <- data.frame(code, time, DV1, DV2, DV3, DV4)
outANOVA <- list()
for (i in names(dat)) {
y <- dat[[i]]
outANOVA[i] <- summary(aov(y ~ factor(time) + Error(factor(code)),
data = dat))
}
outANOVA
Run Code Online (Sandbox Code Playgroud)
Moo*_*per 13
你可以这样写它,它更紧凑:
outANOVA <-
lapply(dat,function(y)
summary(aov(y ~ factor(time) + Error(factor(code)),data = dat)))
Run Code Online (Sandbox Code Playgroud)
for循环不一定比应用函数慢(并且确实可以更快,因为@thc在评论中提到)但对于许多人来说它们不太容易阅读.这在某种程度上是一种品味问题.
真正的犯罪是for在矢量化函数可用时使用循环.这些向量化函数通常包含用C语言编写的for循环速度快得多(或者调用函数).
请注意,在这种情况下,我们也可以避免创建全局变量y,并且我们不必初始化列表outANOVA.
另一点,直接来自这个相关的帖子:对于R中的循环和计算速度(由Glen_b回答):
对于R中的循环并不总是比其他方法慢,例如apply - 但是有一个巨大的bugbear - •永远不会在循环内生成一个数组
相反,在循环之前使数组成为全尺寸,然后填充它们.
在你的情况下,你正在成长outANOVA,对于大循环,它可能会成为问题.
以下是microbenchmark一个简单示例的一些不同方法:
n <- 100000
microbenchmark::microbenchmark(
preallocated_vec = {x <- vector(length=n); for(i in 1:n) {x[i] <- i^2}},
preallocated_vec2 = {x <- numeric(n); for(i in 1:n) {x[i] <- i^2}},
incremented_vec = {x <- vector(); for(i in 1:n) {x[i] <- i^2}},
preallocated_list = {x <- vector(mode = "list", length = n); for(i in 1:n) {x[i] <- i^2}},
incremented_list = {x <- list(); for(i in 1:n) {x[i] <- i^2}},
sapply = sapply(1:n, function(i) i^2),
lapply = lapply(1:n, function(i) i^2),
times=20)
# Unit: milliseconds
# expr min lq mean median uq max neval
# preallocated_vec 9.784237 10.100880 10.686141 10.367717 10.755598 12.839584 20
# preallocated_vec2 9.953877 10.315044 10.979043 10.514266 11.792158 12.789175 20
# incremented_vec 74.511906 79.318298 81.277439 81.640597 83.344403 85.982590 20
# preallocated_list 10.680134 11.197962 12.382082 11.416352 13.528562 18.620355 20
# incremented_list 196.759920 201.418857 212.716685 203.485940 205.441188 393.522857 20
# sapply 6.557739 6.729191 7.244242 7.063643 7.186044 9.098730 20
# lapply 6.019838 6.298750 6.835941 6.571775 6.844650 8.812273 20
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
278 次 |
| 最近记录: |