正确地将 for 循环转换为并行循环

2024-06-23

我这里有这个数据集(例如,学生在几年内多次参加考试,要么通过,要么失败——我有兴趣研究上一次测试对下一次测试的影响):

   id = sample.int(10000, 100000, replace = TRUE)
res = c(1,0)
results = sample(res, 100000, replace = TRUE)
date_exam_taken = sample(seq(as.Date('1999/01/01'), as.Date('2020/01/01'), by="day"), 100000, replace = TRUE)


my_data = data.frame(id, results, date_exam_taken)
my_data <- my_data[order(my_data$id, my_data$date_exam_taken),]

my_data$general_id = 1:nrow(my_data)
my_data$exam_number = ave(my_data$general_id, my_data$id, FUN = seq_along)
my_data$general_id = NULL

     id results date_exam_taken exam_number
7992   1       1      2004-04-23           1
24837  1       0      2004-12-10           2
12331  1       1      2007-01-19           3
34396  1       0      2007-02-21           4
85250  1       0      2007-09-26           5
11254  1       1      2009-12-20           6

我写了这个标准的 FOR LOOP ,一切似乎都工作正常:

my_list = list()

for (i in 1:length(unique(my_data$id)))
    
{ 
    {tryCatch({
        
        start_i = my_data[my_data$id == i,]
        
        pairs_i =  data.frame(first = head(start_i$results, -1), second = tail(start_i$results, -1))
        frame_i =  as.data.frame(table(pairs_i))
        frame_i$id = i
        print(frame_i)
        my_list[[i]] = frame_i
    }, error = function(e){})
    }}


 final_a = do.call(rbind.data.frame, my_list)

现在,我尝试使用 R 中的“doParallel”库来“优化”这个循环。

使用这篇文章(如何在R中的“foreach”循环中转换“for循环”? https://stackoverflow.com/questions/55506788/how-to-transform-a-for-loop-in-a-foreach-loop-in-r)作为教程,我尝试按如下方式转换我的循环:

# does this mean I should set makeCluster() to makeCluster(8)???
 > detectCores()
[1] 8

my_list = list()
max = length(unique(my_data$id))

library(doParallel)
registerDoParallel(cl <- makeCluster(3))

# note: for some reason, this loop isn't printing?

test = foreach(i = 1:max, .combine = "rbind") %dopar% {

    {tryCatch({
        
        start_i = my_data[my_data$id == i,]
        
        pairs_i =  data.frame(first = head(start_i$results, -1), second = tail(start_i$results, -1))
        frame_i =  as.data.frame(table(pairs_i))
        frame_i$id = i
        print(frame_i)
        my_list[[i]] = frame_i
    }, error = function(e){})
    }}


 final_b = do.call(rbind.data.frame, test)

基于此 - 我有以下问题:

  • 我是否正确使用了“doParallel”功能,因为它们的用途是什么?

  • 还有更好的方法吗?

  • Note:我希望在具有大约 1000 万个唯一 ID 的数据集上运行此代码


这是一种将并行代码编写为函数的方法。
我事先按id拆分数据,而不是将每个id与当前索引进行比较i。这可以节省一些时间。它还可以节省提取时间results向量仅一次。

我不知道为什么,我在并行代码中没有发现任何错误,但是最终的 data.frame 不等于顺序输出final_a,它有更多行.

这取决于系统,但正如您在计时中看到的,6 核运行速度最快。

library(parallel)
library(doParallel)
#> Loading required package: foreach
#> Loading required package: iterators

parFun <- function(my_data, ncores) {
  split_data <- split(my_data, my_data$id)
  
  registerDoParallel(cl <- makeCluster(ncores))
  on.exit(stopCluster(cl))
  
  test <- foreach(i = seq_along(split_data)) %dopar% {
    start_i_results <- split_data[[i]]$results
    n <- length(start_i_results)
    if(n > 1L) {
      tryCatch({
        pairs_i <- data.frame(first = start_i_results[-n], 
                              second = start_i_results[-1L])
        frame_i <- as.data.frame(table(pairs_i))
        frame_i$id <- i
        frame_i
      }, error = function(e) {e})
    } else NULL
  }
  final_b <- do.call(rbind.data.frame, test)
  final_b
}

set.seed(2022)
id <- sample.int(10000, 100000, replace = TRUE)
res <- c(1,0)
results <- sample(res, 100000, replace = TRUE)
date_exam_taken <- sample(seq(as.Date('1999/01/01'), as.Date('2020/01/01'), by="day"), 100000, replace = TRUE)
my_data <- data.frame(id, results, date_exam_taken)

my_data <- my_data[order(my_data$id, my_data$date_exam_taken),]

my_data$general_id = 1:nrow(my_data)
my_data$exam_number = ave(my_data$general_id, my_data$id, FUN = seq_along)
my_data$general_id = NULL

t0 <- system.time({
  my_list = list()
  
  for (i in 1:length(unique(my_data$id)))
    
  { 
    {tryCatch({
      
      start_i = my_data[my_data$id == i,]
      
      pairs_i =  data.frame(first = head(start_i$results, -1), second = tail(start_i$results, -1))
      frame_i =  as.data.frame(table(pairs_i))
      frame_i$id = i
      # print(frame_i)
      my_list[[i]] = frame_i
    }, error = function(e){})
    }}
  final_a = do.call(rbind.data.frame, my_list)
})

ncores <- detectCores()

# run with 3 cores
t3 <- system.time(parFun(my_data, 3L))
# run with 6 cores and save the result in `res6`
t6 <- system.time(res6 <- parFun(my_data, ncores - 2L))
rbind(t0, t3, t6)[,1:3]
#>    user.self sys.self elapsed
#> t0     12.86     1.00   15.37
#> t3      3.50     0.22    8.37
#> t6      3.61     0.46    7.65

head(final_a, 10)
#>    first second Freq id
#> 1      0      0    2  1
#> 2      1      0    3  1
#> 3      0      1    4  1
#> 4      1      1    0  1
#> 5      0      0    5  2
#> 6      1      0    3  2
#> 7      0      1    2  2
#> 8      1      1    0  2
#> 9      0      0    0  3
#> 10     1      0    1  3
head(res6, 10)
#>    first second Freq id
#> 1      0      0    2  1
#> 2      1      0    3  1
#> 3      0      1    4  1
#> 4      1      1    0  1
#> 5      0      0    5  2
#> 6      1      0    3  2
#> 7      0      1    2  2
#> 8      1      1    0  2
#> 9      0      0    0  3
#> 10     1      0    1  3

str(final_a)
#> 'data.frame':    38945 obs. of  4 variables:
#>  $ first : Factor w/ 2 levels "0","1": 1 2 1 2 1 2 1 2 1 2 ...
#>  $ second: Factor w/ 2 levels "0","1": 1 1 2 2 1 1 2 2 1 1 ...
#>  $ Freq  : int  2 3 4 0 5 3 2 0 0 1 ...
#>  $ id    : int  1 1 1 1 2 2 2 2 3 3 ...
str(res6)
#> 'data.frame':    38949 obs. of  4 variables:
#>  $ first : Factor w/ 2 levels "0","1": 1 2 1 2 1 2 1 2 1 2 ...
#>  $ second: Factor w/ 2 levels "0","1": 1 1 2 2 1 1 2 2 1 1 ...
#>  $ Freq  : int  2 3 4 0 5 3 2 0 0 1 ...
#>  $ id    : int  1 1 1 1 2 2 2 2 3 3 ...

Created on 2022-12-11 with reprex v2.0.2 https://reprex.tidyverse.org


Edit

以下版本似乎更快。

parFun2 <- function(my_data, ncores) {
  registerDoParallel(cl <- makeCluster(ncores))
  on.exit(stopCluster(cl))
  
  results_list <- split(my_data$results, my_data$id)
  
  test <- foreach(i = seq_along(results_list)) %dopar% {
    start_i_results <- results_list[[i]]
    n <- length(start_i_results)
    if(n > 1L) {
      tbl <- table(first = start_i_results[-n], 
                   second = start_i_results[-1L])
      frame_i <- as.data.frame(tbl)
      frame_i$id <- i
      frame_i
    } else NULL
  }
  data.table::rbindlist(test)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正确地将 for 循环转换为并行循环 的相关文章

  • 随着数据帧变大,如何防止 rbind() 变得非常慢?

    我有一个只有 1 行的数据框 为此 我开始使用 rbind 添加行 df mydataframe with only one row for i in 1 20000 df lt rbind df newrow 随着我的成长 这变得非常缓慢
  • 使用 dplyr::filter 创建 R 函数问题

    我查看了其他答案 但找不到使下面的代码起作用的解决方案 基本上 我正在创建一个函数inner join两个数据框和filter基于函数中输入的列 问题是filter部分功能不起作用 但是 如果我将过滤器从函数中取出并附加它 它就会起作用my
  • 在 heatmap.2 中将行标签设置为斜体

    我正在尝试使用 R 函数将行标签设置为斜体heatmap 2 没有默认选项 我无法通过设置找到解决方法par font 3 例如 如何将行标签设置为斜体heatmap 2 set seed 123 data matrix sample 10
  • 在 R Markdown 中,无论输出类型如何(pdf、html、docx),都在每个页面上创建页眉/页脚

    我想补充一下问题 当我编织为 pdf 时 那里的代码 也在下面 对我来说工作得非常好 但我不会获得 html 或 docx 输出的页眉 页脚 在 R Markdown 中 无论输出文档的类型如何 我可以做什么来为输出文档的每个页面生成页眉
  • 使用 data.table::fwrite() 写入 .txt 文件 — is.list(x) 不为 TRUE

    我试图替换基本 R 函数write table with data table fwrite 加快写入速度 但该函数抱怨说is list x is not TRUE 我提供的输入有什么问题fwrite 期望 但是write table 默默
  • 更改分配新变量的默认环境

    我经常想在全局环境下的一个环境中创建很多变量 这可以通过以下方式轻松完成envir论证sys source 如果由正在获取的文件创建的所有变量都应该进入单个环境 但我通常使用创建变量集的文件 一组应该进入一个环境 另一组应该进入另一个环境
  • R 中二维核密度估计的混乱

    核密度估计器用于估计特定的概率密度函数 参见mvstat net http www mvstat net tduong research seminars seminar 2001 05 and scikit learn 文档 http s
  • 如何使用 Delphi 并行检查拼写?

    我有一种用 Delphi 编写的拼写检查器 它逐句分析文本 它在解析每个句子后根据一些规则对错误的项目进行着色 用户能够中断此过程 这一点很重要 我如何使用一些第 3 方 Delphi 库并行化这个过程 在当前状态下 我在检查后已经对句子进
  • 当 R 中出现“warnings()”时中断循环

    我有一个问题 我正在运行一个循环来处理多个文件 我的矩阵非常巨大 因此如果我不小心 我经常会耗尽内存 如果创建任何警告 是否有办法打破循环 它只是继续运行循环并报告它在很久以后失败 烦人 聪明的 stackoverflow ers 有什么想
  • 如何使用 caret 包解释模型输出的准确性

    我正在使用 caret 包来训练模型 并希望获得模型的准确性 我听说的一种常见方法是使用confusionMatrix 然而 当我运行下面的代码时 经过训练的模型给出了一些与confuseMatrix 报告的精度值略有不同的精度值 所以我的
  • dplyr 通过评估查找单元格值来改变特定列

    我已经使用定额 符号和求值探索了各种选项 但我似乎无法获得正确的语法 这是一个示例数据框 data frame A letters 1 4 B letters 26 23 C letters c 1 3 5 7 D letters c 2
  • knitr pandoc:“无法使用 pdf writer 生成 pdf 输出”

    Up front using pandoc 在knitr中 当尝试将 md或 Rmd编译为PDF时 它会抱怨 我正在简化流程可重复的研究 正如许多地方所记录的那样 我在用着pandoc and knitr并制作出色的文档 我还试图为一些不太
  • 如何在闪亮的应用程序中初始化渲染项目的默认值

    介绍 In a shinyApp 我想用动态输入渲染输出 我的问题是 使用shinydashboard使用不同的选项卡 默认值来自 Input 仅当激活相应选项卡时才会呈现 想想输入和输出选项卡 当使用时我得到同样的行为switch声明in
  • 使用 R 并行处理 XML 节点

    我正在尝试与 R 并行处理 XML 文档xml2包装和foreach功能 但我收到 node attrs x node nsMap ns 中的错误 外部指针无效 尝试导出树集群导出 示例代码 library xml2 library for
  • 如何使用 ggplot2 在轴标签中使用上标

    如何在x轴上打印埃平方 我尝试如下 labs x x axis 2 y y axis 我们可以用bquote library ggplot2 ggplot mtcars aes hp mpg geom point labs x bquote
  • 从谷歌街道地址中提取城市和州信息

    我有一个数据集 其中包含不同点位置的纬度 经度信息 我想知道与每个点关联的城市和州 按照此example https stackoverflow com questions 22911642 applying revgeocode to a
  • R 矩阵到犰狳的转换非常慢

    观察 对于中等大小的矩阵 将矩阵从 R 传递到 C 的开销要慢得多arma mat类型比NumericMatrix类型 大约需要 250 倍的时间 这是一个最小的例子 include
  • 使用同一变量的多个子集创建新数据框

    我想创建一个新的数据框 其中的列是由不同变量分割的同一变量的子集 例如 我想创建一个新的变量子集 b 其中列由不同变量 year 的子集分割 set seed 88 df lt data frame year rep 1996 1998 3
  • 在 ggplot2 中隐藏单个几何图例

    我将相同的变量 颜色 映射到两个不同几何图形中的颜色 我希望它们要么出现在单独的图例中 DHJ 和 EFI 要么最好完全跳过第二个图例 对于 E F 和 I 目前 R 将两者混合在一起 并给我一个图例 其中按字母顺序列出了 DEFHIJ 所
  • 根据值绘制具有条件颜色的折线图

    我想绘制折线图 根据值 它应该改变它的颜色 我发现的是 plot sin seq from 1 to 10 by 0 1 type p col ifelse sin seq from 1 to 10 by 0 1 gt 0 5 red ye

随机推荐

  • 从 .gitlab-ci.yml 中的 JSON 中提取徽章 ID

    我有一个示例项目 https gitlab com mstein badge number example repo在 gitlab 中 我想获取最后一个徽章的 ID gitlab ci yml通过脚本 我了解所有徽章的概览作为 json
  • 如何避免 Google App Engine 标准环境中 Gorilla 会话的内存泄漏?

    我正在使用 Gorilla 在 Google App Engine 上启用会话变量 到目前为止 我只导入了 github com gorilla sessions 但 Gorilla 的页面显示 如果您不使用 gorilla mux 则需要
  • 将 Dynamo DB 流数据解组为 Json 格式

    我必须将DDB流消息转换为正常的json类型 为此我正在使用 unmarshalleddata aws DynamoDB Converter unmarshall result NewImage 其中 result NewImage 是 c
  • 如何在 Angular js 中创建动态工厂?

    在我的项目中 我必须在 Angular js 中创建动态工厂 其动态工厂名称如下 function createDynamicFactory modId return myModule factory modId existingServi
  • 从对象数组中删除重复项

    我有一堂课叫Customer它有几个字符串属性 例如 firstName lastName email etc 我从a读取客户信息csv创建类数组的文件 Customer customers 我需要删除具有相同电子邮件地址的重复客户 为每个
  • GUID 幕后花絮

    我想知道 GUID 的创建过程是怎样的 我的意思不是用什么来以特定语言创建 GUID SQL Server 中的 NewID C 中的 Guid NewGuid 我的意思是当你调用这些方法 函数时 它们会做什么来使图形用户界面 Also R
  • 如何在 Python 中打印异常?

    如何打印错误 异常except block try except print exception 对于 Python 2 6 及更高版本和 Python 3 x except Exception as e print e 对于 Python
  • 如何在 PHP 中解析 OFX(版本 1.0.2)文件?

    我有一个OFX http www ofx net 文件下载自Citibank https www citibank com co 该文件的 DTD 定义在http www ofx net DownloadPage Files ofx102s
  • 从 Laravel 中的命令调用控制器方法

    我有一个通过 Redis Pub Sub 监听的命令 收到发布后 我想调用控制器方法 以便可以更新数据库 但是 我无法找到任何关于如何从项目内部但在路由外部调用带有参数的控制器方法的解决方案 我见过的最接近的东西是这样的 return re
  • R Shiny Dashboard 在初始化时不会在 sidebarMenu 内加载渲染的 UI

    我正在尝试根据用户希望如何提供输入来生成动态的 UI 元素 为了简单起见 我使用闪亮的仪表板 但我遇到了侧边栏菜单的问题 以前 当我将静态 UI 元素直接放入 sidebarMenu 中时 没有任何问题 但是当尝试将动态 UI 元素放入 s
  • 什么是日历队列?

    我正在致力于构建一个离散事件模拟器 维基百科提到有几种通用优先级队列非常适合在 DES 中使用 具体来说 它提到日历队列是一个很好的结构 我找到了一份 pdf 1988 年的 其中提到了日历队列 但在大多数情况下我找不到关于它们的任何其他内
  • 如何在 python 套接字中使用浏览器作为客户端?

    我试图在互联网上搜索这个主题 但我没有找到一些答案 如果有人知道如何在 python 套接字中使用浏览器作为客户端 那就太好了 要将浏览器用作 python 服务器 套接字的客户端 您只需将其指向正确的端点即可 假设您在同一台计算机上运行浏
  • 当脚本执行暂停时,如何在 chrome devtools 中运行异步代码?

    await Promise resolve 1 在 chrome devtools chrome 版本 70 0 3538 77 中解析为 1当脚本执行未暂停时 Promise
  • 整个 Inno Setup 安装程序的完整性检查

    我们使用 Inno Setup 作为安装程序 最近有用户在安装过程中报告如下错误 尝试复制文件时发生错误 源文件已损坏 这是由于安装文件确实已损坏 理想情况下 安装 EXE 会在初始化时执行某种检查 以查看整个 EXE 是否有效 但显然它只
  • C# Directory.exist 在本地网络上始终返回 false

    我正在尝试检查目录是否存在于非网络或本地网络上 经过对 stackoverflow 和 MSDN 的一些研究后 我使用模拟方法开发了我的代码 问题是它运作得不太好 Directory exists 方法总是返回False这是我的代码 它与来
  • 迷你分析器 nullreferenceException

    当我正在运行的存储过程执行迷你分析器时 它会抛出空引用并导致我的应用程序停止 在这种情况下 SP 不会返回任何内容 这是堆栈跟踪 at MvcMiniProfiler MiniProfiler AddSqlTiming SqlTiming
  • Javascript 将相同的类添加到 Div,而不需要为每个 Div 进行计算

    我显示了 2 张优惠券 它们都有 new coupon 而实际上一张应该说 new coupon 一张应该说 old coupon 它似乎为页面上具有该类的每个元素应用相同的类 而不是计算每个元素应该属于哪个类 jQuery documen
  • 如何在 Silverlight 4 中释放 COM 对象

    当将 COM Interop 与 Office 通常是 Excel 一起使用时 我总是小心地确保我调用Marshal ReleaseComObject在每个引用上 以避免 Excel 不退出的问题如本知识库文章中所述 http suppor
  • 错误:未指定默认引擎且未提供扩展名

    我正在使用 node js 和引擎设置 http 服务器 但是 我不断遇到一些问题 我对如何解决这个问题知之甚少 我希望能得到一些帮助来解决这个问题 Error No default engine was specified and no
  • 正确地将 for 循环转换为并行循环

    我这里有这个数据集 例如 学生在几年内多次参加考试 要么通过 要么失败 我有兴趣研究上一次测试对下一次测试的影响 id sample int 10000 100000 replace TRUE res c 1 0 results sampl