繁体   English   中英

R 中的并行计算,用于在循环中保存数据

[英]Parallel computation in R for saving data over loops

我在以下简单代码上应用并行以在多个循环中使用 Openxlsx 保存输出的努力失败了。

任何人都可以帮助将此代码转换为并行模式。 此代码基于真实大小的数据(超过 5000 万次观察,需要 13 小时才能运行)。 甚至减少 2 小时对我来说都是一项艰巨的工作。

library(dplyr)
library(readxl)
library(openxlsx)
library(foreach)
library(doParallel)


rawdata <- readxl::read_xlsx("~/Desktop/Book1.xlsx")


TYPE1 <- rawdata %>% filter(TYPE == "A") 
TYPE2 <- rawdata %>% filter(TYPE == "B") 

Split.TYPE1 <- split(TYPE1, TYPE1$Name) 
Split.TYPE2 <- split(TYPE2, TYPE2$Name) 


#--------------------------------- Save the TYPE A reports------------------------------------------------------------------------------
###################################(the foreach lines are coded)
for (nm in names(Split.TYPE1)){
#foreach(nm=1:names(Split.TYPE1), .combine=cbind) %dopar% {
  file<-paste0(nm,".xlsx")
  d1<-as.data.frame(Split.TYPE1[[nm]])

  wb<-createWorkbook(file)
  addWorksheet(wb, "test", gridLines = T)
  writeData(wb, sheet = "test", x = d1)
  saveWorkbook(wb, file, overwrite = TRUE)
}

# #------------------------------ Save the TYPE B in a folder ----------------------------------
for (dn in names(Split.TYPE2)){
   dnn <- paste0(dn)
  dir.create(dnn)
  sub_Split.TYPE2 <- split(Split.TYPE2[[dn]], Split.TYPE2[[dn]]$Surname)
  for (fn in names(sub_Split.TYPE2)){
    file<-file.path(dnn, paste0(fn,".xlsx"))

    d1<-as.data.frame(sub_Split.TYPE2[[fn]])
    wb<-createWorkbook(file)
    addWorksheet(wb, "test", gridLines = T)
    writeData(wb, sheet = "test", x = d1)
    saveWorkbook(wb, file, overwrite = TRUE)
  }}

数据:

Name    Surname TYPE
John    Greer   A
David   bear    A
Rose    beer    B
Tara    tea     B
Sam     Mac     B
Alan    Glass   B
Brad    Newman  A
Kristen Goodman A
Jessica Goodwin A
Heather Poker   B

因为我没有你的数据,所以我做了一些小的虚拟样本。

我使用的软件包:

library(tidyverse)
library(openxlsx)
library(foreach)
library(doParallel)

这部分来自你并没有改变任何东西。

TYPE1 <- rawdata %>% filter(TYPE == "A") 
TYPE2 <- rawdata %>% filter(TYPE == "B") 

Split.TYPE1 <- split(TYPE1, TYPE1$Name) 
Split.TYPE2 <- split(TYPE2, TYPE2$Name) 

定义并行后端。 我在这里使用 6 个内核。

cl <- makeCluster(6)
registerDoParallel(cl)

这是你的第一个循环。 不要忘记添加.packages = "openxlsx" 这确保包也被发送给工作人员。 我稍微更改了代码,因为nm in names(Split.TYPE1)不适用于 foreach。 也许有更简单的解决方案,但我不知道。

foreach(nm = 1:length(Split.TYPE1), .combine = cbind, .packages = "openxlsx") %dopar% {
  file <- paste0(names(Split.TYPE1)[nm], ".xlsx")
  d1 <- as.data.frame(Split.TYPE1[[names(Split.TYPE1)[nm]]])

  wb <- createWorkbook(file)
  addWorksheet(wb, "test", gridLines = TRUE)
  writeData(wb, sheet = "test", x = d1)
  saveWorkbook(wb, file, overwrite = TRUE)
}

第二个循环。 我过去只用过一次,对我来说效果很好。 这就是如何创建嵌套的 foreach 循环。 更多信息在这里

foreach(dn = 1:length(Split.TYPE2)) %:%
  foreach(fn = 1:length(unique(Split.TYPE2[[names(Split.TYPE2)[dn]]]$Surname)), .packages = "openxlsx") %dopar% {
    dnn <- paste0(names(Split.TYPE2)[dn])
    dir.create(dnn)
    sub_Split.TYPE2 <- split(Split.TYPE2[[names(Split.TYPE2)[dn]]], Split.TYPE2[[names(Split.TYPE2)[dn]]]$Surname)


    file <- file.path(dnn, paste0(names(sub_Split.TYPE2)[fn],".xlsx"))

    d1 <- as.data.frame(sub_Split.TYPE2[[fn]])
    wb <- createWorkbook(file)
    addWorksheet(wb, "test", gridLines = T)
    writeData(wb, sheet = "test", x = d1)
    saveWorkbook(wb, file, overwrite = TRUE)
  }

并停止并行后端。

stopCluster(cl)

使用您的数据,我为嵌套循环获得以下文件夹/文件结构:

- Alan
    - Glass.xlsx
- Heather
    - Poker.xlsx
- Rose
    - beer.xlsx
- Sam
    - Mac.xlsx
- Tara
    - tea.xlsx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM