从 Foreach 获取等于 R 中 for 循环结果的输出
Get output from Foreach equal to result from for loop in R
我目前正在将 for
循环转换为 foreach
循环,以便我可以并行化内循环的计算。我能够做到这一点并获得正确的输出。但是,我希望 foreach
的输出格式与我在旧 for
循环中的格式相同。这是我想做的一个可重现的例子:
FOR 循环:
x <- c(1:10)
y <- c(5)
z <- c(3)
result_list <- list()
for(i in length(x)){
for(j in 1:y){
for(k in 1:z){
result <- rnorm(n = 250)
result_list[[paste(i, j, k)]] <- result
}
}
}
这就是我得到的结果以及我想要实现的目标:
library(dplyr)
glimpse(result_list)
List of 15
$ 10 1 1: num [1:250] -0.382 -0.156 -0.747 1.139 -1.824 ...
$ 10 1 2: num [1:250] -0.181 0.526 0.255 -0.369 -1.517 ...
$ 10 1 3: num [1:250] 0.3621 1.3634 -0.0507 -0.3943 -1.2183 ...
$ 10 2 1: num [1:250] -1.453 0.731 2.761 -0.586 -1.631 ...
$ 10 2 2: num [1:250] -0.663 -0.641 -1.852 1.58 0.133 ...
$ 10 2 3: num [1:250] -1.334 0.803 -0.116 0.618 -1.339 ...
$ 10 3 1: num [1:250] 0.158 -1.296 -0.947 -0.515 -0.208 ...
$ 10 3 2: num [1:250] -0.604 1.956 0.127 1.846 -0.549 ...
$ 10 3 3: num [1:250] 0.365 -0.467 -0.589 -1.251 0.491 ...
$ 10 4 1: num [1:250] -1.138 0.883 1 0.729 -1.566 ...
$ 10 4 2: num [1:250] -0.0461 2.3096 -1.5347 0.3722 0.3125 ...
$ 10 4 3: num [1:250] 0.127 -0.728 0.402 1.783 -1.457 ...
$ 10 5 1: num [1:250] 1.855 2.224 1.301 0.166 -0.28 ...
$ 10 5 2: num [1:250] 0.463 -1.011 1.067 -1.305 -0.51 ...
$ 10 5 3: num [1:250] 1.937 0.651 -0.424 -0.714 -0.225 ...
这是 FOREACH 循环的代码:
library(foreach)
result_list <- list()
resultado_foreach <- foreach::foreach(i = 1:10, .inorder = TRUE) %do% {
foreach::foreach(j = 1:5, .inorder = TRUE) %do% {
foreach::foreach((k = 1:3)) %dopar% {
result <- rnorm(n = 250)
result_list[[paste(i, j, k)]] <- result
}
}
}
尽管如此,我得到了列表列表的列表(嵌套列表):
glimpse(resultado_foreach)
List of 10
$ :List of 5
..$ :List of 3
.. ..$ : num [1:250] 0.911 0.594 -0.453 0.651 2.303 ...
.. ..$ : num [1:250] -0.664 -0.696 0.741 -2.78 -0.992 ...
.. ..$ : num [1:250] -0.6877 -1.1266 -1.7784 0.473 0.0185 ...
..$ :List of 3
.. ..$ : num [1:250] 1.273 0.129 0.902 2.47 0.177 ...
.. ..$ : num [1:250] 0.705 0.519 1.219 -1.682 -0.355 ...
.. ..$ : num [1:250] 1.138 0.422 -1.025 -0.237 0.418 ...
..$ :List of 3
.. ..$ : num [1:250] -1.636 -1.297 -1.115 -0.138 0.174 ...
.. ..$ : num [1:250] 0.56 -1.311 0.641 0.861 -0.601 ...
.. ..$ : num [1:250] 0.198 -1.197 0.781 -0.571 -0.141 ...
..$ :List of 3
.. ..$ : num [1:250] -0.355 -0.649 -1.046 -0.717 -0.97 ...
.. ..$ : num [1:250] -1.086 0.912 -0.996 0.303 1.418 ...
.. ..$ : num [1:250] 0.8827 -0.0761 1.3504 -0.5301 0.2267 ...
..$ :List of 3
.. ..$ : num [1:250] -1.826 1.286 1.585 -0.359 -0.955 ...
.. ..$ : num [1:250] -0.588 -0.314 -0.223 -0.779 0.569 ...
.. ..$ : num [1:250] 1.047 -0.242 -0.345 0.27 -0.158 ...
foreach
输出比我在这里放的要长得多。
我已经尝试了很多组合,并在 foreach
函数中将许多函数设置为 .combine
参数。那么,我怎样才能获得与 for loop
?
格式相同的输出呢?
目前在你的 for 循环中你有
for(i in length(x)) {...}
但是 length(x)
是 10 所以你只是在做 for(i in 10)
只循环一次。这与 for (i in 1:10)
不同。更安全的选择是 for (i in seq_along(x))
.
假设您需要 10 个外部循环,每个循环有 5 个中间循环,每个循环有 3 个内部循环。那应该是 10x5x3 = 150 个总结果。
如果你想为每个使用嵌套循环,你应该使用 %:%
运算符。另外,您还需要使用 .combine=c
将内部循环连接到最后的单个列表中。 ?foreach
帮助页面上讨论了这些选项。
更好的版本是
resultado_foreach <-
foreach::foreach(i = 1:10, .inorder = TRUE, .combine=c) %:%
foreach::foreach(j = 1:5, .inorder = TRUE, .combine=c) %:%
foreach::foreach((k = 1:3)) %dopar% {
rnorm(n = 250)
}
这将 return 一个长度为 150 的列表,每个列表都有一个长度为 250 的向量。
请注意,使用 foreach
时不应修改全局变量。每个块应该 return 一个值,foreach
将为您收集并组合这些值。
我目前正在将 for
循环转换为 foreach
循环,以便我可以并行化内循环的计算。我能够做到这一点并获得正确的输出。但是,我希望 foreach
的输出格式与我在旧 for
循环中的格式相同。这是我想做的一个可重现的例子:
FOR 循环:
x <- c(1:10)
y <- c(5)
z <- c(3)
result_list <- list()
for(i in length(x)){
for(j in 1:y){
for(k in 1:z){
result <- rnorm(n = 250)
result_list[[paste(i, j, k)]] <- result
}
}
}
这就是我得到的结果以及我想要实现的目标:
library(dplyr)
glimpse(result_list)
List of 15
$ 10 1 1: num [1:250] -0.382 -0.156 -0.747 1.139 -1.824 ...
$ 10 1 2: num [1:250] -0.181 0.526 0.255 -0.369 -1.517 ...
$ 10 1 3: num [1:250] 0.3621 1.3634 -0.0507 -0.3943 -1.2183 ...
$ 10 2 1: num [1:250] -1.453 0.731 2.761 -0.586 -1.631 ...
$ 10 2 2: num [1:250] -0.663 -0.641 -1.852 1.58 0.133 ...
$ 10 2 3: num [1:250] -1.334 0.803 -0.116 0.618 -1.339 ...
$ 10 3 1: num [1:250] 0.158 -1.296 -0.947 -0.515 -0.208 ...
$ 10 3 2: num [1:250] -0.604 1.956 0.127 1.846 -0.549 ...
$ 10 3 3: num [1:250] 0.365 -0.467 -0.589 -1.251 0.491 ...
$ 10 4 1: num [1:250] -1.138 0.883 1 0.729 -1.566 ...
$ 10 4 2: num [1:250] -0.0461 2.3096 -1.5347 0.3722 0.3125 ...
$ 10 4 3: num [1:250] 0.127 -0.728 0.402 1.783 -1.457 ...
$ 10 5 1: num [1:250] 1.855 2.224 1.301 0.166 -0.28 ...
$ 10 5 2: num [1:250] 0.463 -1.011 1.067 -1.305 -0.51 ...
$ 10 5 3: num [1:250] 1.937 0.651 -0.424 -0.714 -0.225 ...
这是 FOREACH 循环的代码:
library(foreach)
result_list <- list()
resultado_foreach <- foreach::foreach(i = 1:10, .inorder = TRUE) %do% {
foreach::foreach(j = 1:5, .inorder = TRUE) %do% {
foreach::foreach((k = 1:3)) %dopar% {
result <- rnorm(n = 250)
result_list[[paste(i, j, k)]] <- result
}
}
}
尽管如此,我得到了列表列表的列表(嵌套列表):
glimpse(resultado_foreach)
List of 10
$ :List of 5
..$ :List of 3
.. ..$ : num [1:250] 0.911 0.594 -0.453 0.651 2.303 ...
.. ..$ : num [1:250] -0.664 -0.696 0.741 -2.78 -0.992 ...
.. ..$ : num [1:250] -0.6877 -1.1266 -1.7784 0.473 0.0185 ...
..$ :List of 3
.. ..$ : num [1:250] 1.273 0.129 0.902 2.47 0.177 ...
.. ..$ : num [1:250] 0.705 0.519 1.219 -1.682 -0.355 ...
.. ..$ : num [1:250] 1.138 0.422 -1.025 -0.237 0.418 ...
..$ :List of 3
.. ..$ : num [1:250] -1.636 -1.297 -1.115 -0.138 0.174 ...
.. ..$ : num [1:250] 0.56 -1.311 0.641 0.861 -0.601 ...
.. ..$ : num [1:250] 0.198 -1.197 0.781 -0.571 -0.141 ...
..$ :List of 3
.. ..$ : num [1:250] -0.355 -0.649 -1.046 -0.717 -0.97 ...
.. ..$ : num [1:250] -1.086 0.912 -0.996 0.303 1.418 ...
.. ..$ : num [1:250] 0.8827 -0.0761 1.3504 -0.5301 0.2267 ...
..$ :List of 3
.. ..$ : num [1:250] -1.826 1.286 1.585 -0.359 -0.955 ...
.. ..$ : num [1:250] -0.588 -0.314 -0.223 -0.779 0.569 ...
.. ..$ : num [1:250] 1.047 -0.242 -0.345 0.27 -0.158 ...
foreach
输出比我在这里放的要长得多。
我已经尝试了很多组合,并在 foreach
函数中将许多函数设置为 .combine
参数。那么,我怎样才能获得与 for loop
?
目前在你的 for 循环中你有
for(i in length(x)) {...}
但是 length(x)
是 10 所以你只是在做 for(i in 10)
只循环一次。这与 for (i in 1:10)
不同。更安全的选择是 for (i in seq_along(x))
.
假设您需要 10 个外部循环,每个循环有 5 个中间循环,每个循环有 3 个内部循环。那应该是 10x5x3 = 150 个总结果。
如果你想为每个使用嵌套循环,你应该使用 %:%
运算符。另外,您还需要使用 .combine=c
将内部循环连接到最后的单个列表中。 ?foreach
帮助页面上讨论了这些选项。
更好的版本是
resultado_foreach <-
foreach::foreach(i = 1:10, .inorder = TRUE, .combine=c) %:%
foreach::foreach(j = 1:5, .inorder = TRUE, .combine=c) %:%
foreach::foreach((k = 1:3)) %dopar% {
rnorm(n = 250)
}
这将 return 一个长度为 150 的列表,每个列表都有一个长度为 250 的向量。
请注意,使用 foreach
时不应修改全局变量。每个块应该 return 一个值,foreach
将为您收集并组合这些值。