如何为使用itertools chunking的R foreach()语句编写一个combine函数,这样我得到与使用R foreach()语句而没有itertools chunking相同的结果?
我有一个R foreach()语句执行计算并返回三个列表的列表。在第一个代码块中提供了一个提供所需输出的简化版本 - 它使用了我在Saving multiple outputs of foreach dopar loop找到的组合函数。
现在我想使用itertools中的chunking来运行相同的代码。我尝试了这两种不同的方式(参见下面的第二和第三个代码块),但都没有产生预期的结果。问题是,在我尝试合并itertools chunking时,三个列表由3个列表组成,包括2个列表(在不同的尝试中有2个不同长度的列表),而不是由3个10个列表的列表组成的三个列表。我猜这些列表的长度是2而不是10,因为我的计算机上的num_cores是2 - 这告诉我,在使用itertools chunking时,我的组合函数可能需要更改才能正确组合输出。我很难搞清楚如何改变它。我该如何更改组合功能?
这是生成所需结果的foreach()语句:
# set up
library(foreach)
library(doParallel)
# set parallel options
num_cores_total <- detectCores()
num_cores <- num_cores_total - 2
cl <- makeCluster(spec= num_cores, type="PSOCK")
registerDoParallel(cl, cores = num_cores)
# create function that will separate out foreach output into list of three lists
comb <- function(x, ...) {
lapply(seq_along(x),
function(i) c(x[[i]], lapply(list(...), function(y) y[[i]])))
}
# foreach statement
three_lists <- foreach(i = 1:10, .inorder=TRUE, .combine='comb', .multicombine=TRUE, .init=list(list(), list(), list())) %dopar% {
first_output <- i*1
second_output <- i*10
third_output <- i*100
list(first_output, second_output, third_output)
}
first_output_list <- three_lists[[1]]
second_output_list <- three_lists[[2]]
third_output_list <- three_lists[[3]]
这是我第一次(不成功)尝试将itertools分块合并到代码中:
# set up
library(foreach)
library(itertools)
library(doParallel)
# set parallel options
num_cores_total <- detectCores()
num_cores <- num_cores_total - 2
cl <- makeCluster(spec= num_cores, type="PSOCK")
registerDoParallel(cl, cores = num_cores)
# create function that will separate out foreach output into list of three lists
comb <- function(x, ...) {
lapply(seq_along(x),
function(i) c(x[[i]], lapply(list(...), function(y) y[[i]])))
}
# foreach statement
three_lists <- foreach(thisIter=isplitIndices(10, chunks=num_cores), .inorder=TRUE, .combine='comb', .multicombine=TRUE, .init=list(list(), list(), list())) %dopar% {
first_output <- thisIter*1
second_output <- thisIter*10
third_output <- thisIter*100
list(first_output, second_output, third_output)
}
first_output_list <- three_lists[[1]]
second_output_list <- three_lists[[2]]
third_output_list <- three_lists[[3]]
# stop cluster
stopCluster(cl)
这是我第二次(不成功)尝试将itertools分块合并到代码中:
# set up
library(foreach)
library(itertools)
library(doParallel)
# set parallel options
num_cores_total <- detectCores()
num_cores <- num_cores_total - 2
cl <- makeCluster(spec= num_cores, type="PSOCK")
registerDoParallel(cl, cores = num_cores)
# create function that will separate out foreach output into list of three lists
comb <- function(x, ...) {
lapply(seq_along(x),
function(i) c(x[[i]], lapply(list(...), function(y) y[[i]])))
}
# foreach statement
three_lists <- foreach(thisIter=isplitIndices(10, chunks=num_cores), .inorder=TRUE, .combine='comb', .multicombine=TRUE, .init=list(list(), list(), list())) %dopar% {
calc_function <- function(x){
first_output <- x*1
second_output <- x*10
third_output <- x*100
return(list(first_output, second_output, third_output))
}
sapply(thisIter, calc_function)
}
first_output_list <- three_lists[[1]]
second_output_list <- three_lists[[2]]
third_output_list <- three_lists[[3]]
# stop cluster
stopCluster(cl)
答案 0 :(得分:0)
我们的想法是,您可以使用.combine=c
附加以块的形式返回的列表
(这样你就不会得到嵌套列表),
然后在没有itertools
的情况下以你的方式调整结构
(但有点简化):
lists <- foreach(thisIter=isplitIndices(10L, chunks=num_cores), .combine=c) %dopar% {
lapply(thisIter, function(i) {
c(i * 1L,
i * 10L,
i * 100L)
})
}
first_output_list <- lapply(lists, "[", 1L)
second_output_list <- lapply(lists, "[", 2L)
third_output_list <- lapply(lists, "[", 3L)