问题描述
我正在尝试对4维数组执行操作。这个数组最终变得非常大,但是对于我正在处理的数据来说是必需的。现在,过程本身开始膨胀,但是我想为并行计算做好准备。我可以使用96核大型机,我想使用它。
到目前为止,我已经在线阅读了最简单的方法是使用mclapply(),它是lapply()的并行版本。我知道lapply()的工作原理,但我不太想知道如何在这种情况下应用它。
我有一个充满NA的4维数组。每个维度都有一个昏暗的名字。我想比较维度1与维度3的暗名,以及维度2与维度4的暗名(这是由我编写的自定义函数完成的)。如果它们全部匹配,就会出现一个数字,我希望将该数字输入到xy [i,k,j,l]中,其中字母i-l代表一个条目的索引。
在下面的示例中,我将其简化为为暗名添加的nchar()值。
xy <- array(NA,dim = c(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","pete","melinda","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
该函数实际上返回一个数值向量,但是通过将[]
保留在xy[]<-
中,您可以通过保持xy
的属性不变来将值分配回xy
使其成为多维数组。
此解决方案不能在Windows上并行工作。
不需要 do.call
,因为expand.grid
将data.frame的每一列(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]])