并行计算,在dplyr中完成tidyr::complete的哪种替代方案?

并行计算,在dplyr中完成tidyr::complete的哪种替代方案?,r,dplyr,parallel-processing,multidplyr,R,Dplyr,Parallel Processing,Multidplyr,我正在试着使一根管子平行。 在管道中有一个tidyr命令(“tidyr::complete”)。这会在并行运行时分解代码,因为无法识别对象类 dplyr中是否有其他选项需要完成 library(dplyr) library(tidyr) library(zoo) test <- tibble(year=c(1,2,3,4,5,5,1,4,5), var_1=c(1,1,1,1,1,1,2,2,2), var_2=c(1,1,

我正在试着使一根管子平行。 在管道中有一个tidyr命令(“tidyr::complete”)。这会在并行运行时分解代码,因为无法识别对象类

dplyr中是否有其他选项需要完成

library(dplyr)
library(tidyr)
library(zoo)


test <- tibble(year=c(1,2,3,4,5,5,1,4,5),
               var_1=c(1,1,1,1,1,1,2,2,2), 
               var_2=c(1,1,1,1,1,2,3,3,3), 
               var_3=c(0,5,NA,15,20,NA,1,NA,NA))

max_year <- max(test$year,na.rm = T)
min_year <- min(test$year,na.rm = T)


Multidplyr允许您:

  • 使用
    partition()
  • 在专用节点上处理每个分区
  • collect()
    结果
  • 并非所有数据处理任务都适用于以前的工作流

    特别是,
    complete
    需要知道输入数据中所有可能的值,以便创建缺少的行,这意味着此操作作为一个整体无法拆分,这就是为什么没有可用的方法

    在您提供的示例中,每个节点将接收一个
    var_1,var_2
    对,而不知道其他节点得到了什么,这不允许并行实现预期结果

    但是,正如您已经知道的那样,
    year=seq(minu_year,max_year)
    ,您可以仅为该变量并行化
    complete
    任务,通过
    var_1
    拆分任务,例如使用
    furr
    包:

    library(furrr)
    plan(multiprocess)
    test_parallel <- test %>% 
      group_by(var_1,var_2) %>% 
      complete(var_1) %>% split(.$var_1) %>% 
      furrr::future_map(~{
        complete(.x, year = seq(min_year,max_year)) %>%
        dplyr::mutate(
            var_3 = na.approx(var_3,na.rm = FALSE),
            var_3 = if(all(is.na(var_3))) NA else na.spline(var_3,na.rm = FALSE)) 
        }) %>% bind_rows()
    
    > identical(c(test_serial$var_1,test_serial$var_2,test_serial$var_3,test_serial$year),
    +           c(test_parallel$var_1,test_parallel$var_2,test_parallel$var_3,test_parallel$year))
    [1] TRUE
    
    库(furr)
    计划(多进程)
    测试单元并行%
    分组依据(变量1,变量2)%>%
    完成(var_1)%%>%拆分(.$var_1)%%>%
    未来地图(~{
    完成(.x,年=序号(最小年,最大年))%>%
    dplyr::突变(
    var_3=近似值(var_3,na.rm=假),
    var_3=if(all(is.na(var_3)))na else na.spline(var_3,na.rm=FALSE))
    })%%>%bind_行()
    >相同(c(测试序列$var_1、测试序列$var_2、测试序列$var_3、测试序列$year),
    +c(测试并行$var_1、测试并行$var_2、测试并行$var_3、测试并行$year))
    [1] 真的
    

    要在更大的数据集上进行测试以衡量潜在的改进。

    但是,如果我能够为每个节点分配一个完整的组来完成(比如var_1),那么我是否能够使用complete?我得到了以下警告:#警告消息:[一次性警告]分叉处理(“多核”)在将来被禁用(>=1.13.0)从RStudio运行R时,因为它被认为是不稳定的。因此,计划(“多核”)将退回计划(“顺序”),计划(“多进程”)将退回计划(“多段”)——而不是过去的计划(“多核”)。有关更多详细信息,如何控制分叉处理与否,以及如何在将来的R会话中消除此警告,请参阅?future::supportsMulticoreAs proof,system.time()显示,Furr解决方案比标准的oneMultitasking慢4倍。在小示例数据集上,多任务处理通常要慢,因为您需要打开任务,将数据传输给他们并收集结果,这比直接处理数据花费的时间要多出15行,请参见我的最后一句;-)
    devtools::install_github("hadley/multidplyr")
    library(multidplyr)
    
    cl <- new_cluster(2)
    cluster_copy(cl, c("test","max_year","min_year"))
    cluster_library(cl, c("dplyr","tidyr","zoo"))
    
    test_parallel <- test %>% group_by(var_1,var_2) %>% partition(cl)
    test_parallel <- test_parallel %>% 
      dplyr::group_by(var_1,var_2) %>% 
      tidyr::complete(var_1, year = seq(min_year,max_year)) %>%
      dplyr::mutate(
        var_3 = na.approx(var_3,na.rm = FALSE),
        var_3 = if(all(is.na(var_3))) NA else na.spline(var_3,na.rm = FALSE)) %>% 
      collect()
    
    
    Error in UseMethod("complete_") : 
      no applicable method for 'complete_' applied to an object of class "multidplyr_party_df"
    
    library(furrr)
    plan(multiprocess)
    test_parallel <- test %>% 
      group_by(var_1,var_2) %>% 
      complete(var_1) %>% split(.$var_1) %>% 
      furrr::future_map(~{
        complete(.x, year = seq(min_year,max_year)) %>%
        dplyr::mutate(
            var_3 = na.approx(var_3,na.rm = FALSE),
            var_3 = if(all(is.na(var_3))) NA else na.spline(var_3,na.rm = FALSE)) 
        }) %>% bind_rows()
    
    > identical(c(test_serial$var_1,test_serial$var_2,test_serial$var_3,test_serial$year),
    +           c(test_parallel$var_1,test_parallel$var_2,test_parallel$var_3,test_parallel$year))
    [1] TRUE