Как разделить фрейм данных для параллельной обработки, а затем повторно объединить результаты?

#r #foreach #parallel-processing #parallel.foreach #doparallel

#r #foreach #параллельная обработка #parallel.foreach #doparallel

Вопрос:

Я хочу разделить фрейм данных для параллельной обработки, чтобы ускорить время обработки.

Что у меня есть до сих пор (неработающий код):

 library(tidyverse)
library(iterators)
library(doParallel)
library(foreach)

data_split <- split(iris, iris$Species)
data_iter <- iter(data_split)

cl <- makeCluster(3)
registerDoParallel(cl)

foreach(
  data=data_iter,
  i = data_iter,
  .combine=dplyr::bind_rows
  
) %dopar% {
  test <- lm(Petal.Length ~ Sepal.Length, i)
  test.lm <- broom::augment(test)
  
  return(dplyr::bind_rows(test.lm))
}

stopCluster(cl)
  

Может быть, lapply в foreach?

 out <- foreach(it = data_iter,
               .combine = dplyr::bind_rows,
               .multicombine = TRUE,
               .noexport = ls()
) %dopar% {
  print(str(it, max.level = 1))
  out <- lapply(it, function(x) {
    test <- lm(Petal.Length ~ Sepal.Length, subset(iris, iris$Species == iris$Species[[x]]))
    test.lm <- broom::augment(test)
  })
}
print(bind_rows(out))
return(bind_rows(out))
  

Что я собираюсь сделать:

 test1 <- lm(Petal.Length ~ Sepal.Length, subset(iris, iris$Species == iris$Species[[1]]))
test.lm1 <- broom::augment(test1)

test2 <- lm(Petal.Length ~ Sepal.Length, subset(iris, iris$Species == iris$Species[[2]]))
test.lm2 <- broom::augment(test2)

test3 <- lm(Petal.Length ~ Sepal.Length, subset(iris, iris$Species == iris$Species[[3]]))
test.lm3 <- broom::augment(test3)

testdat <- bind_rows(test.lm1,test.lm2,test.lm3)
  

Ответ №1:

Я нашел свой ответ в furrr пакете:

 library(furrr)

plan(cluster, workers = 3)

data_split <- split(iris, iris$Species)

testdat <- furrr::future_map_dfr(data_split, function(.data){
  test <- lm(Petal.Length ~ Sepal.Length, .data)
  broom::augment(test)
})

plan(cluster, workers = 1)

testdat
  

Комментарии:

1. Нет необходимости в параллельном пакете и его registerDoParallel() регистрации. Если makeCluster() stopCluster() вам нужны and , то они находятся в параллельном пакете.

2. Вы также можете пропустить makeCluster() и использовать plan(cluster, workers = 3) напрямую.

3. Есть ли furrr функция остановки кластера?

4. Если вы используете plan(cluster, workers = 3) then, вы можете остановить этот кластер, перейдя на другой план, например plan(sequential) . Это из будущего пакета, который furrr создает сверху.

5. Кстати, используйте plan(multisession, workers = 3) , который в основном такой же, как plan(cluster, workers = 3) . Я использовал только cluster в своем первом комментарии, чтобы сделать его максимально похожим на то, что у вас уже есть.