用 mclapply() 替换多维数组上的嵌套 for 循环
replace nested for-loops on multidimensional array with mclapply()
我正在尝试对 4 维数组执行操作。这个数组最终变得非常大,但对于我正在处理的数据来说是必需的。现在这个过程本身会膨胀,但我想让它为并行计算做好准备。我有一台96核的主机,我想使用它。
到目前为止,我在网上了解到完成此操作的最简单方法是使用 mclapply(),lapply() 的并行化版本。我知道 lapply() 的基本工作原理,但我不太清楚如何在这种情况下应用它。
我有一个充满 NA 的 4 维数组。每个维度都有 dimnames。我想比较维度 1 和维度 3 以及维度 2 和维度 4 的 dimnames(这是通过我编写的自定义函数完成的)。如果它们都匹配,就会出现一个数字,我希望将该数字输入到 xy[i, k, j, l] 中,其中字母 i-l 代表一个条目的索引。
在下面的示例中,我将其简化为添加 dimnames 的 nchar() 值。
xy <- array(NA, dim = c(10, 10, 10, 10), dimnames = list(c("john", "sandra", "peter", "linda", "max", "sam", "ana", "enzo", "juan", "abe"),
c("smith", "gonzalez", "doe", "dopi", "lincoln", "biden", "rutte", "merkel", "slim", "shady"),
c("jon", "sam", "pete", "melinda", "max", "sam", "anna", "carlo", "jiro", "abel"),
c("smitty", "rupinder", "dole", "mite", "lincolan", "bidet", "rourke", "meer", "smart", "sunny")))
for(i in 1:dim(xy)[1]){
for(j in 1:dim(xy)[3]){
for(k in 1:dim(xy)[2]){
for(l in 1:dim(xy)[4]){
a <- nchar(dimnames(xy)[[1]][i]) + nchar(dimnames(xy)[[3]][j])
b <- nchar(dimnames(xy)[[2]][k]) + nchar(dimnames(xy)[[4]][l])
if(!is.null(a) & !is.null(b)){
xy[i, k, j, l] <- a + b
}
}
}
}
}
我的问题是我的输出需要是一个多维数组。到目前为止,我只使用 lapply() 来输出一个值列表。我如何将其扩展到多个维度?
我已经看过这些帖子了:
replace a nested for loop with mapply
但是每一个都以对我没有帮助的方式解决问题。
fun_on_names <- function(Var1, Var2, Var3, Var4){
a <- nchar(Var1) + nchar(Var3)
b <- nchar(Var2) + nchar(Var4)
if(!is.null(a) & !is.null(b)) return(a + b)
else return(NA)
}
xy[] <- do.call(parallel::mcmapply,
c(list(FUN = fun_on_names, mc.cores = 96),
expand.grid(dimnames(xy), stringsAsFactors = FALSE)))
想法是:
- 用
expand.grid
创建一个大 data.frame 的所有名称组合。
- 对每个组合应用函数
fun_on_names
- 将结果应用回
xy
该函数实际上 returns 一个数字向量,但是通过将 []
保留在 xy[]<-
中,您可以通过保持完整的属性将值分配回 xy
xy
这使它成为一个多维数组。
此解决方案无法在 Windows 上并行运行。
do.call
不需要 data.frame 的每一列(expand.grid
的输出)被 mcapply
视为单独的向量。
您可以将其视为:
df <- expand.grid(dimnames(xy), stringsAsFactors = FALSE)
xy[] <- parallel::mcmapply(FUN = fun_on_names,
mc.cores = 96,
df[[1]], df[[2]], df[[3]], df[[4]])
我正在尝试对 4 维数组执行操作。这个数组最终变得非常大,但对于我正在处理的数据来说是必需的。现在这个过程本身会膨胀,但我想让它为并行计算做好准备。我有一台96核的主机,我想使用它。
到目前为止,我在网上了解到完成此操作的最简单方法是使用 mclapply(),lapply() 的并行化版本。我知道 lapply() 的基本工作原理,但我不太清楚如何在这种情况下应用它。
我有一个充满 NA 的 4 维数组。每个维度都有 dimnames。我想比较维度 1 和维度 3 以及维度 2 和维度 4 的 dimnames(这是通过我编写的自定义函数完成的)。如果它们都匹配,就会出现一个数字,我希望将该数字输入到 xy[i, k, j, l] 中,其中字母 i-l 代表一个条目的索引。
在下面的示例中,我将其简化为添加 dimnames 的 nchar() 值。
xy <- array(NA, dim = c(10, 10, 10, 10), dimnames = list(c("john", "sandra", "peter", "linda", "max", "sam", "ana", "enzo", "juan", "abe"),
c("smith", "gonzalez", "doe", "dopi", "lincoln", "biden", "rutte", "merkel", "slim", "shady"),
c("jon", "sam", "pete", "melinda", "max", "sam", "anna", "carlo", "jiro", "abel"),
c("smitty", "rupinder", "dole", "mite", "lincolan", "bidet", "rourke", "meer", "smart", "sunny")))
for(i in 1:dim(xy)[1]){
for(j in 1:dim(xy)[3]){
for(k in 1:dim(xy)[2]){
for(l in 1:dim(xy)[4]){
a <- nchar(dimnames(xy)[[1]][i]) + nchar(dimnames(xy)[[3]][j])
b <- nchar(dimnames(xy)[[2]][k]) + nchar(dimnames(xy)[[4]][l])
if(!is.null(a) & !is.null(b)){
xy[i, k, j, l] <- a + b
}
}
}
}
}
我的问题是我的输出需要是一个多维数组。到目前为止,我只使用 lapply() 来输出一个值列表。我如何将其扩展到多个维度?
我已经看过这些帖子了:
replace a nested for loop with mapply
但是每一个都以对我没有帮助的方式解决问题。
fun_on_names <- function(Var1, Var2, Var3, Var4){
a <- nchar(Var1) + nchar(Var3)
b <- nchar(Var2) + nchar(Var4)
if(!is.null(a) & !is.null(b)) return(a + b)
else return(NA)
}
xy[] <- do.call(parallel::mcmapply,
c(list(FUN = fun_on_names, mc.cores = 96),
expand.grid(dimnames(xy), stringsAsFactors = FALSE)))
想法是:
- 用
expand.grid
创建一个大 data.frame 的所有名称组合。 - 对每个组合应用函数
fun_on_names
- 将结果应用回
xy
该函数实际上 returns 一个数字向量,但是通过将 []
保留在 xy[]<-
中,您可以通过保持完整的属性将值分配回 xy
xy
这使它成为一个多维数组。
此解决方案无法在 Windows 上并行运行。
do.call
不需要 data.frame 的每一列(expand.grid
的输出)被 mcapply
视为单独的向量。
您可以将其视为:
df <- expand.grid(dimnames(xy), stringsAsFactors = FALSE)
xy[] <- parallel::mcmapply(FUN = fun_on_names,
mc.cores = 96,
df[[1]], df[[2]], df[[3]], df[[4]])