R dopar foreach逐块而不是每行

时间:2019-03-08 17:12:33

标签: r foreach data-manipulation doparallel

此问题特定于在R中使用foreach和dopar进行并行处理。我创建了一个简单的数据集和一个简单的操作(实际操作更加复杂,因此在此我将展示一个简单的操作)。数据代码和当前代码已发布,供您参考。

加载程序包并创建数据

#Creating a mock dataframe
Area =c('XX','YY','ZZ','XX','YY','ZZ','XX','YY','ZZ','YY')
Car_type = c('A','A','B','C','B','C','A','A','B','C')
Variable1=c(.34,.19,.85,.27,.32,.43,.22,.56,.17,.11)
Variable2=c(.76,.3,.16,.24,.47,.23,.87,.27,.43,.59)
Final_data = data.frame(Area,Car_type,Variable1,Variable2)    
#replicate the above 100 times to create a bigger dataset
n =100
Final_data2=do.call("rbind", replicate(n, Final_data, simplify = FALSE))
Final_data2$Final_value = 0
#car_list = unique(Final_data2$Car_type) #have not figured out how to use this

dopar foreach代码

#Create clusters and load required packages the clusters 
library(doParallel)    
cl=makeCluster(3,type="PSOCK") 
registerDoParallel(cl)


home1 <- function(zz1){
  output <- foreach(x = iter(zz1, by = "row"), .combine = rbind, 
                    .packages = "truncnorm") %dopar% {
    if (x$Car_type=='A'){
      x$Final_value = rtruncnorm(1,a=-1,b=1,mean = x$Variable1,sd=x$Variable2)
    } else if(x$Car_type=='B'){
      x$Final_value = rtruncnorm(1,a=-5,b=5,mean = x$Variable1,sd=1)  
    }  else{
      x$Final_value = rtruncnorm(1,a=-10,b=10,mean = 1,sd=1)
    }
    return(x)
  }
  output
}
Final_data3 <- home1(zz1=Final_data2)
stopCluster(cl) #Stop cluster

在第一部分中,我创建了一个名为Final_data2的示例数据帧。 在第二部分中,基于“ Car_type”列中的汽车类型,我从截断的正态分布生成一个值,其中截断点以及均值和标准差根据Car_type而变化。该代码以当前格式工作。使用不同的内核后,它会在每一行中进行迭代。

问题

现在,我想以一种方式扩展它,而不是在单独的核心上迭代和运行操作,而不是在数据集的块上运行操作。我想做的是在单独的内核上为不同区域运行dopar foreach部分。对于前。我想为群集1上的Area = XX和群集3上的Area = YY以及群集3上的Area = ZZ运行dopar foreach循环。不幸的是,我无法自己弄清楚这一点。有人可以帮我吗?任何帮助将不胜感激。

修改 正如Prive指出的那样,最初的问题有点令人困惑。我已经稍微修改了这个问题。请让我知道现在是否更清楚了。

1 个答案:

答案 0 :(得分:1)

对于您的特定应用程序,我会使用pmap::purrr()

home2 <- function(Car_type, Variable1, Variable2) {
  if (Car_type=='A'){
    truncnorm::rtruncnorm(1,a=-1,b=1,mean = Variable1,sd=Variable2)
  } else if(Car_type=='B'){
    truncnorm::rtruncnorm(1,a=-5,b=5,mean = Variable1,sd=1)  
  }  else{
    truncnorm::rtruncnorm(1,a=-10,b=10,mean = 1,sd=1)
  }
}

Final_data2$Final_value <- 
  purrr::pmap_dbl(Final_data2[c("Car_type", "Variable1", "Variable2")], home2)

如果此操作确实需要很长时间,则可以使用软件包{future}和{furrr}对其进行并行化:

future::plan(future::multiprocess)
Final_data2$Final_value <- 
  furrr::future_pmap_dbl(Final_data2[c("Car_type", "Variable1", "Variable2")], home2)