在R中并行循环

时间:2019-03-10 23:13:25

标签: r parallel-processing data-manipulation

我正在尝试学习如何在R中使用并行处理。下面提供了数据和代码的快照。

创建一个粗糙的数据集

library(truncnorm)
#Creating a mock dataframe
Market =c('City1','City2','City3','City4','City5','City2','City4','City1','City3','City5')
Car_type = c('A','A','A','A','A','B','B','B','B','B')
Variable1=c(.34,.19,.85,.27,.32,.43,.22,.56,.17,.11)
Car_purchased = c(1,0,0,1,0,1,0,0,1,1)
Market_data = data.frame(Market,Car_type,Variable1,Car_purchased)    
Market_data2=do.call("rbind", replicate(100, Market_data, simplify = FALSE)) 
#Create a bigger dataset
Market_data2$Final_value = 0 #create a column of for future calculation
empty_list = list()

编写函数并运行该函数

Car_Value=function(data){
  market_list=unique(Market_data2$Market)
  for (m in market_list){
    market_subset = Market_data2[which(Market_data2$Market==m),]
    for (i in 1:nrow(market_subset)){
      if(market_subset[i,'Car_purchased']==1){
        market_subset[i,'Final_value'] = rtruncnorm(1,a=-10,b=0,mean=max(market_subset$Variable1),sd=1)
      } else{
        market_subset[i,'Final_value'] = rtruncnorm(1,a=-10,b=0,mean = market_subset[i,'Variable1'],sd=1)
      }
    }
    empty_list=rbind(empty_list,market_subset)
  }
  return(empty_list)
}

get_value = Car_Value(data=Market_data2)

在上面的示例中,总共有5个汽车“市场”和2个“ Car_type”。消费者可能在两个市场上都购买了汽车。我必须从给定的截断正态分布中计算一个值(“ Final_value”)。该值仅取决于给定市场的Variable1的值。这就是为什么我使用外部for循环。截断正态分布的均值取决于Variable1的值(如果Car_purchased == 1,则为市场中的max(Variable1);如果Car_purchased == 0,则为给定值)。此版本的代码运行得很好(尽管尚未针对速度进行优化)。

问题

接下来,我要对外部for循环(即整个市场的循环)使用并行处理,因为市场的Final_value仅取决于市场内的观察结果。

不幸的是,我只知道如何为数据集的每一行实现并行处理。例如。我的代码(下面提供)将第一行分配给第一核,将第二行分配给第二核,依此类推。这效率低下,并且需要花费很长时间,因为每行必须创建子集,然后找到子集的最大值。

我的低效率版本

library(parallel)
library(foreach)
library(doParallel)
library(iterators)
library(utils)
library(truncnorm)

cl=parallel::makeCluster(4,type="PSOCK") 
registerDoParallel(cl)
clusterEvalQ(cl, {library(truncnorm)})

Car_Value_Parallel <- function(market_data){
  output <- foreach(x = iter(market_data, by = "row"), .combine = rbind) %dopar% {
    market_subset = market_data[which(market_data$Market==x$Market),]
    if(x['Car_purchased']==1){
      x['Final_value'] = rtruncnorm(1,a=-10,b=0,mean=max(market_subset$Variable1),sd=1)
    } else{
      x['Final_value'] = rtruncnorm(1,a=-10,b=0,mean = x['Variable1'],sd=1)
    }
    return(x)
  }
  output
}

get_value_parallel = Car_Value_Parallel(market_data = Market_data2)
stopCluster(cl)

如果我在大小> 100K的数据集上运行它,效率将非常低(我的实际数据集约为120万行)。 但是,我无法在市场级别实现并行化,并行计算将如下:在第一个核心中运行City1,在第二个核心中运行City2,依此类推。救命?任何帮助表示赞赏。谢谢。

P.S。对于长期的问题,我深表歉意。我只想显示我使用过的所有代码版本。

0 个答案:

没有答案