如何将函数并行应用于表并存储结果 - R

时间:2018-01-10 17:30:52

标签: r parallel.foreach doparallel

我试图通过表格中的所有行来应用某些功能。类似的东西:

for(i in 1:nrow(df)){
   df[i,2] <- somefunction1(df[i,1])
   df[i,3] <- somefunction2(df[i,1])
   df[i,3] <- somefunction3(df[i,1])
   df[i,4] <- somefunction4(df[i,1])
}

这可行,但需要太长时间,所以我在考虑与库 doParallel 进行并行化。但是当我尝试:

foreach(i = 1:nrow(df) ) %dopar% {
   df[i,2] <- somefunction1(df[i,1])
   df[i,3] <- somefunction2(df[i,1])
   df[i,3] <- somefunction3(df[i,1])
   df[i,4] <- somefunction4(df[i,1])}

它不会更改表,但会返回包含最后一个函数结果的列表。

我想也许这不是我想达到的最佳方法所以我愿意接受新的方法来提高这种代码的效率。这是excel表在不花费太多时间的情况下自动同时对所有单元格进行的操作,因此我认为R应该能够以某种方式执行此操作。

如果要实现并行化,我希望得到一些关于如何将结果直接存储在循环内的表格的方向,而不是分别执行每个函数并在此之后存储它(它使代码变慢而且更少结果与变量的关联是可靠的。)

提前谢谢。

2 个答案:

答案 0 :(得分:0)

这不是并行化的问题。

{ }之间的代码就像函数一样。请参阅以下示例

myfun <- function() {
   1
   2
   3
}

myfun()
# 3

最后一个评估值存在隐式return,其他评估值将丢失。你的“功能”也是如此

foreach(i = 1:nrow(df) ) %dopar% {
  df[i,2] <- somefunction1(df[i,1])
  df[i,3] <- somefunction2(df[i,1])
  df[i,3] <- somefunction3(df[i,1])
  df[i,4] <- somefunction4(df[i,1])}

您可以将其修改为

foreach(i = 1:nrow(df) ) %dopar% {
  c(somefunction1(df[i,1]), somefunction2(df[i,1]), somefunction3(df[i,1]), somefunction4(df[i,1])) }

返回评估值的向量

其次,可以说更重要的是,你应该尝试改变你的函数来接受向量和返回向量。而不是

df[i,2] <- somefunction1(df[i,1])   # single element in vector

尝试

df[,2] <- somefunction1(df[,1])     # entire vector

答案 1 :(得分:0)

这是在数据帧中的每一行上执行函数的一种非常低效的方法。您是否必须使用for循环?

以下是一些在数据框中的行上并行运行一些简单函数的代码:

a <- sample(1:1000)

df <- as.data.frame(cbind(a))

somefunction1 <- function(x) {
  x/1
}

somefunction2 <- function(x) {
  x/2
}

somefunction3 <- function(x) {
  x/3
}

somefunction4 <- function(x) {
  x/4
}

for(i in 1:nrow(df)){
  df[i,1] <- somefunction1(df[i,1])
  df[i,2] <- somefunction2(df[i,1])
  df[i,3] <- somefunction3(df[i,1])
  df[i,4] <- somefunction4(df[i,1])
}

library(foreach)
library(doMC)
library(abind)

registerDoMC(detectCores()-1)

acomb <- function(...) abind(..., along=1)

par_df <- foreach(i=icount(nrow(df)), .combine='acomb', .multicombine=TRUE) 
%dopar%
{

  df[i,1] <- somefunction1(df[i,1])
  df[i,2] <- somefunction2(df[i,1])
  df[i,3] <- somefunction3(df[i,1])
  df[i,4] <- somefunction4(df[i,1])

  df[i,]

}

par_df_2 <- data.frame(par_df, stringsAsFactors=FALSE)