R dopar foreach 在块上而不是每行
R dopar foreach on chunks instead of per line
此问题特定于使用 foreach 和 dopar 在 R 中使用并行处理。我创建了一个简单的数据集和一个简单的操作(实际操作更复杂,因此我在这里展示一个简单的操作)。把数据的代码和当前的代码贴出来供大家参考。
加载包并创建数据
#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" 中的汽车类型,我从 t运行 正态分布生成一个值,其中 t运行 阳点以及均值和标准差发生变化取决于Car_type。此代码适用于当前格式。它在使用不同的内核后遍历每一行。
问题
现在我想以这样一种方式扩展它,而不是在单独的核心上迭代和 运行 对每一行的操作进行操作,我想 运行 对块的操作数据集。我想做的是 运行 dopar foreach 部分用于不同核心上的不同区域。对于前。我想 运行 集群 1 上的 Area = XX、集群 2 上的 Area = YY 和集群 3 上的 Area = ZZ 的 dopar foreach 循环。不幸的是,我无法自己解决这个问题。有人会帮我吗?任何帮助将不胜感激。
编辑
正如 Prive 指出的那样,最初的问题有点令人困惑。我稍微修改了这个问题。如果现在更清楚一点,请告诉我。
对于您的特定应用程序,我会使用 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)
此问题特定于使用 foreach 和 dopar 在 R 中使用并行处理。我创建了一个简单的数据集和一个简单的操作(实际操作更复杂,因此我在这里展示一个简单的操作)。把数据的代码和当前的代码贴出来供大家参考。
加载包并创建数据
#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" 中的汽车类型,我从 t运行 正态分布生成一个值,其中 t运行 阳点以及均值和标准差发生变化取决于Car_type。此代码适用于当前格式。它在使用不同的内核后遍历每一行。
问题
现在我想以这样一种方式扩展它,而不是在单独的核心上迭代和 运行 对每一行的操作进行操作,我想 运行 对块的操作数据集。我想做的是 运行 dopar foreach 部分用于不同核心上的不同区域。对于前。我想 运行 集群 1 上的 Area = XX、集群 2 上的 Area = YY 和集群 3 上的 Area = ZZ 的 dopar foreach 循环。不幸的是,我无法自己解决这个问题。有人会帮我吗?任何帮助将不胜感激。
编辑 正如 Prive 指出的那样,最初的问题有点令人困惑。我稍微修改了这个问题。如果现在更清楚一点,请告诉我。
对于您的特定应用程序,我会使用 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)