将for循环转换为foreach循环
我想通过使用foreach包使下面的代码更高效。我尝试了很长一段时间,但没有得到与使用for循环时相同的结果。我想使用一个嵌套的foreach循环,包括并行化。。。作为输出,我希望有两个dim[R,b1]的矩阵,我非常感谢您的建议将for循环转换为foreach循环,r,foreach,doparallel,R,Foreach,Doparallel,我想通过使用foreach包使下面的代码更高效。我尝试了很长一段时间,但没有得到与使用for循环时相同的结果。我想使用一个嵌套的foreach循环,包括并行化。。。作为输出,我希望有两个dim[R,b1]的矩阵,我非常感谢您的建议 n <- c(100, 300, 500) R <- 100 b0 <- 110 b1 <- seq(0.01, 0.1, length.out = 100) ## all combinations of n and b1 grid &l
n <- c(100, 300, 500)
R <- 100
b0 <- 110
b1 <- seq(0.01, 0.1, length.out = 100)
## all combinations of n and b1
grid <- expand.grid(n, b1)
names(grid) <- c("n", "b1")
calcPower <- function( R, b0, grid) {
cl <- makeCluster(3)
registerDoParallel(cl)
## n and b1 coefficients
n <- grid$n
b1 <- grid$b1
## ensures reproducibility
set.seed(2020)
x <- runif(n, 18, 80)
x.dich <- factor( ifelse( x < median( x), 0, 1))
## enables to store two outputs
solution <- list()
## .options.RNG ensures reproducibility
res <- foreach(i = 1:R, .combine = rbind, .inorder = TRUE, .options.RNG = 666) %dorng% {
p.val <- list()
p.val.d <- list()
for( j in seq_along(b1)) {
y <- b0 + b1[j] * x + rnorm(n, 0, sd = 10)
mod.lm <- lm( y ~ x)
mod.lm.d <- lm( y ~ x.dich)
p.val <- c( p.val, ifelse( summary(mod.lm)$coef[2,4] <= 0.05, 1, 0))
p.val.d <- c( p.val.d, ifelse( summary(mod.lm.d)$coef[2,4] <= 0.05, 1, 0))
}
solution[[1]] <- p.val
solution[[2]] <- p.val.d
return(solution)
}
dp.val <- matrix( unlist(res[,1], use.names = FALSE), R, length(b1), byrow = TRUE)
dp.val.d <- matrix( unlist(res[,2], use.names = FALSE), R, length(b1), byrow = TRUE)
stopCluster(cl)
df <- data.frame(
effectS = b1,
power = apply( dp.val, 2, function(x){ mean(x) * 100}),
power.d = apply( dp.val.d, 2, function(x){ mean(x) * 100}),
n = factor(n))
return(df)
}
## simulation for different n
tmp <- with(grid,
by( grid, n,
calcPower, R = R, b0 = b0))
## combines the 3 results
df.power <- rbind(tmp[[1]], tmp[[2]], tmp[[3]])
n我在下面的代码中创建了一个foreach
循环。必须做出一些改变。在foreach
中返回列表要比返回矩阵容易得多,因为它与rbind
相结合。尤其是当您想要返回多个。我的解决方案是将所有内容保存在列表中,然后将其转换为长度为100的矩阵
注意:您的代码中有一个错误<代码>摘要(mod.lm.d)$coef[2,4]
不存在。我把它改为[2]。适应你的需要
solution <- list()
df2<-foreach(i = 1:R, .combine = rbind, .inorder=TRUE) %dopar%{
set.seed(i)
p.val <- list()
p.val.d <- list()
counter <- list()
for( j in seq_along(b1)){
x <- sort( runif(n, 18, 80))
x.dich <- factor( ifelse( x < median(x), 0, 1))
y <- b0 + b1[j] * x + rnorm( n, 0, sd = 10)
mod.lm <- lm( y ~ x)
mod.lm.d <- lm( y ~ x.dich)
p.val <- c(p.val, ifelse( summary( mod.lm)$coef[2] <= 0.05, 1, 0))
p.val.d <- c(p.val.d, ifelse( summary( mod.lm.d)$coef[2] <= 0.05, 1, 0))
counter <- c(counter, j)
}
solution[[1]] <- p.val
solution[[2]] <- p.val.d
solution[[3]] <- counter
return(solution)
}
dp.val <- unlist(df2[,1], use.names = FALSE)
dp.val.d <- unlist(df2[,2], use.names = FALSE)
dp.val.matr <- matrix(dp.val, R, length(b1))
dp.val.d.matr <- matrix(dp.val.d, R, length(b1))
stopCluster(cl)
solution我在下面的代码中创建了一个foreach
循环。必须做出一些改变。在foreach
中返回列表要比返回矩阵容易得多,因为它与rbind
相结合。尤其是当您想要返回多个。我的解决方案是将所有内容保存在列表中,然后将其转换为长度为100的矩阵
注意:您的代码中有一个错误<代码>摘要(mod.lm.d)$coef[2,4]
不存在。我把它改为[2]。适应你的需要
solution <- list()
df2<-foreach(i = 1:R, .combine = rbind, .inorder=TRUE) %dopar%{
set.seed(i)
p.val <- list()
p.val.d <- list()
counter <- list()
for( j in seq_along(b1)){
x <- sort( runif(n, 18, 80))
x.dich <- factor( ifelse( x < median(x), 0, 1))
y <- b0 + b1[j] * x + rnorm( n, 0, sd = 10)
mod.lm <- lm( y ~ x)
mod.lm.d <- lm( y ~ x.dich)
p.val <- c(p.val, ifelse( summary( mod.lm)$coef[2] <= 0.05, 1, 0))
p.val.d <- c(p.val.d, ifelse( summary( mod.lm.d)$coef[2] <= 0.05, 1, 0))
counter <- c(counter, j)
}
solution[[1]] <- p.val
solution[[2]] <- p.val.d
solution[[3]] <- counter
return(solution)
}
dp.val <- unlist(df2[,1], use.names = FALSE)
dp.val.d <- unlist(df2[,2], use.names = FALSE)
dp.val.matr <- matrix(dp.val, R, length(b1))
dp.val.d.matr <- matrix(dp.val.d, R, length(b1))
stopCluster(cl)
解决方案现在我意识到这与我的假设不符。在foreach循环中不可能使用normal for循环。j始终=1,并且不迭代1:length(b1)。只是想让你知道。很抱歉再次抱怨@Andrea aforeach
确实与for
循环一起工作。我在答案中插入了一个例子。我之前也会检查我的解决方案,不确定是否出了问题。也许我在加入数据时犯了一个错误。@Andrea我想我在处理你的变量时犯了一个错误。我将代码更改为更节省的方式来处理您的问题。我还为您插入了一个计数器变量,您可以使用df2[,3]
调用它。您可以看到j
确实在迭代。但是我建议把它去掉。这只是不必要的时间间隔。现在我意识到这并不是我想象的那样。在foreach循环中不可能使用normal for循环。j始终=1,并且不迭代1:length(b1)。只是想让你知道。很抱歉再次抱怨@Andrea aforeach
确实与for
循环一起工作。我在答案中插入了一个例子。我之前也会检查我的解决方案,不确定是否出了问题。也许我在加入数据时犯了一个错误。@Andrea我想我在处理你的变量时犯了一个错误。我将代码更改为更节省的方式来处理您的问题。我还为您插入了一个计数器变量,您可以使用df2[,3]
调用它。您可以看到j
确实在迭代。但是我建议把它去掉。这只是不必要的时间间隔。