• 主页
  • 课程

    关于课程

    • 课程归档
    • 成为一名讲师
    • 讲师信息
    同等学历教学

    同等学历教学

    免费
    阅读更多
  • 特色
    • 展示
    • 关于我们
    • 问答
  • 事件
  • 个性化
  • 博客
  • 联系
  • 站点资源
    有任何问题吗?
    (00) 123 456 789
    weinfoadmin@weinformatics.cn
    注册登录
    恒诺新知
    • 主页
    • 课程

      关于课程

      • 课程归档
      • 成为一名讲师
      • 讲师信息
      同等学历教学

      同等学历教学

      免费
      阅读更多
    • 特色
      • 展示
      • 关于我们
      • 问答
    • 事件
    • 个性化
    • 博客
    • 联系
    • 站点资源

      R语言

      • 首页
      • 博客
      • R语言
      • 【R】提升R代码运算效率的11个实用方法

      【R】提升R代码运算效率的11个实用方法

      • 发布者 weinfoadmin
      • 分类 R语言
      • 日期 2016年3月11日
      测试开头
                 点击上方“数据工匠”可以订阅哦!

      【R】提升R代码运算效率的11个实用方法

      众所周知,当我们利用 R 语言处理大型数据集时,for 循环语句的运算效率非常低。有许多种方法可以提升你的代码运算效率,但或许你更想了解运算效率能得到多大的提升。本文将介绍几种适用于大数据领域的方法,包括简单的逻辑调整设计、并行处理和 Rcpp 的运用,利用这些方法你可以轻松地处理1亿行以上的数据集。
      让我们尝试提升往数据框中添加一个新变量过程(该过程中包含循环和判断语句)的运算效率。下面的代码输出原始数据框:

      # Create the data frame col1 <- runif (12^5, 0, 2) col2 <- rnorm (12^5, 0, 2) col3 <- rpois (12^5, 3) col4 <- rchisq (12^5, 2) df <- data.frame (col1, col2, col3, col4)

      逐行判断该数据框 (df) 的总和是否大于 4 ,如果该条件满足,则对应的新变量数值为 ’greaterthan4’ ,否则赋值为 ’lesserthan4’ 。

      # Original R code: Before vectorization and pre-allocation system.time({   for (i in 1:nrow(df)) { # for every row     if ((df[i, 'col1'] + df[i, 'col2'] + df[i, 'col3'] + df[i, 'col4']) > 4) { # check if > 4       df[i, 5] <- "greater_than_4" # assign 5th column     } else {       df[i, 5] <- "lesser_than_4" # assign 5th column     }   } })

      本文中所有的计算都在配置了 2.6Ghz 处理器和 8GB 内存的 MAC OS X 中运行。



      【R】提升R代码运算效率的11个实用方法

      1.向量化处理和预设数据库结构

      【R】提升R代码运算效率的11个实用方法


      循环运算前,记得预先设置好数据结构和输出变量的长度和类型,千万别在循环过程中渐进性地增加数据长度。接下来,我们将探究向量化处理是如何提高处理数据的运算速度。

      # after vectorization and pre-allocation output <- character (nrow(df)) # initialize output vector system.time({   for (i in 1:nrow(df)) {     if ((df[i, 'col1'] + df[i, 'col2'] + df[i, 'col3'] + df[i, 'col4']) > 4) {       output[i] <- "greater_than_4"     } else {       output[i] <- "lesser_than_4"     }   } df$output})



      【R】提升R代码运算效率的11个实用方法

      2.将条件语句判断条件移至循环外

      【R】提升R代码运算效率的11个实用方法


      将条件判断语句移至循环外可以提升代码的运算速度,接下来本文将利用包含 100,000行数据至 1,000,000 行数据的数据集进行测试:

      # after vectorization and pre-allocation, taking the condition checking outside the loop. output <- character (nrow(df)) condition <- (df$col1 + df$col2 + df$col3 + df$col4) > 4  # condition check outside the loop system.time({   for (i in 1:nrow(df)) {     if (condition[i]) {       output[i] <- "greater_than_4"     } else {       output[i] <- "lesser_than_4"     }   }   df$output <- output })



      【R】提升R代码运算效率的11个实用方法

      3.只在条件语句为真时执行循环过程

      【R】提升R代码运算效率的11个实用方法


      另一种优化方法是预先将输出变量赋值为条件语句不满足时的取值,然后只在条件语句为真时执行循环过程。此时,运算速度的提升程度取决于条件状态中真值的比例。
      本部分的测试将和 case(2) 部分进行比较,和预想的结果一致,该方法确实提升了运算效率。

      output <- c(rep("lesser_than_4", nrow(df))) condition <- (df$col1 + df$col2 + df$col3 + df$col4) > 4 system.time({     for (i in (1:nrow(df))[condition]) {  # run loop only for true conditions         if (condition[i]) {             output[i] <- "greater_than_4"         }      }     df$output  })



      【R】提升R代码运算效率的11个实用方法

      4.尽可能地使用 ifelse() 语句

      【R】提升R代码运算效率的11个实用方法


      利用 ifelse() 语句可以使你的代码更加简便。 ifelse() 的句法格式类似于 if() 函数,但其运算速度却有了巨大的提升。即使是在没有预设数据结构且没有简化条件语句的情况下,其运算效率仍高于上述的两种方法。

      system.time({   output <- ifelse ((df$col1 + df$col2 + df$col3 + df$col4) > 4, "greater_than_4", "lesser_than_4")   df$output <- output })



      【R】提升R代码运算效率的11个实用方法

      5.使用 which() 语句

      【R】提升R代码运算效率的11个实用方法


      利用 which() 语句来筛选数据集,我们可以达到 Rcpp 三分之一的运算速率。

      # Thanks to Gabe Becker system.time({   want = which(rowSums(df) > 4)   output = rep("less than 4", times = nrow(df))   output[want] = "greater than 4" })  # nrow = 3 Million rows (approx)    user  system elapsed    0.396   0.074   0.481



      【R】提升R代码运算效率的11个实用方法6.用 apply 族函数替代 for 循环语句

      【R】提升R代码运算效率的11个实用方法


      本部分将利用 apply() 函数来计算上文所提到的案例,并将其与向量化的循环语句进行对比。该方法的运算效率优于原始方法,但劣于 ifelse() 和将条件语句置于循环外端的方法。该方法非常有用,但是当你面对复杂的情形时,你需要灵活运用该函数。

      # apply family system.time({   myfunc <- function(x) {     if ((x['col1'] + x['col2'] + x['col3'] + x['col4']) > 4) {       "greater_than_4"     } else {       "lesser_than_4"     }   }   output <- apply(df[, c(1:4)], 1, FUN=myfunc)  # apply 'myfunc' on every row   df$output <- output })



      【R】提升R代码运算效率的11个实用方法

      7.利用compiler包编译函数cmpfun()

      【R】提升R代码运算效率的11个实用方法


      这可能不是说明字节码编译有效性的最好例子,但是对于更复杂的函数而言,字节码编译将会表现地十分优异,因此我们应当了解下该函数。

      # byte code compilation library(compiler) myFuncCmp <- cmpfun(myfunc) system.time({   output <- apply(df[, c (1:4)], 1, FUN=myFuncCmp) })



      【R】提升R代码运算效率的11个实用方法

      8.利用Rcpp

      【R】提升R代码运算效率的11个实用方法


      截至目前,我们已经测试了好几种提升运算效率的方法,其中最佳的方法是利用ifelse()函数。如果我们将数据量增大十倍,运算效率将会变成啥样的呢?接下来我们将利用Rcpp来实现该运算过程,并将其与ifelse()进行比较。

      library(Rcpp) sourceCpp("MyFunc.cpp") system.time (output <- myFunc(df)) # see Rcpp function below

      下面是利用C++语言编写的函数代码,将其保存为“MyFunc.cpp”并利用sourceCpp进行调用。

      // Source for MyFunc.cpp #include  using namespace Rcpp; // [[Rcpp::export]] CharacterVector myFunc(DataFrame x) {   NumericVector col1 = as(x["col1"]);   NumericVector col2 = as(x["col2"]);   NumericVector col3 = as(x["col3"]);   NumericVector col4 = as(x["col4"]);   int n = col1.size();   CharacterVector out(n);   for (int i=0; i 4){       out[i] = "greater_than_4";     } else {       out[i] = "lesser_than_4";     }   }   return out; }



      【R】提升R代码运算效率的11个实用方法

      9.利用并行运算

      【R】提升R代码运算效率的11个实用方法


      并行运算的代码:

      # parallel processing library(foreach) library(doSNOW) cl <- makeCluster(4, type="SOCK") # for 4 cores machine registerDoSNOW (cl) condition <- (df$col1 + df$col2 + df$col3 + df$col4) > 4 # parallelization with vectorization system.time({   output <- foreach(i = 1:nrow(df), .combine=c) %dopar% {     if (condition[i]) {       return("greater_than_4")     } else {       return("lesser_than_4")     }   } })  df$output <- output



      【R】提升R代码运算效率的11个实用方法

      10.尽早移除变量并恢复内存容量

      【R】提升R代码运算效率的11个实用方法


      在进行冗长的循环计算前,尽早地将不需要的变量移除掉。在每次循环迭代运算结束时利用gc()函数恢复内存也可以提升运算速率。



      【R】提升R代码运算效率的11个实用方法

      11.利用内存较小的数据结构

      【R】提升R代码运算效率的11个实用方法


      data.table()是一个很好的例子,因为它可以减少数据的内存,这有助于加快运算速率。

      dt <- data.table(df)  # create the data.table system.time({   for (i in 1:nrow (dt)) {     if ((dt[i, col1] + dt[i, col2] + dt[i, col3] + dt[i, col4]) > 4) {       dt[i, col5:="greater_than_4"]  # assign the output as 5th column     } else {       dt[i, col5:="lesser_than_4"]  # assign the output as 5th column     }   } })



      【R】提升R代码运算效率的11个实用方法

      总结

      【R】提升R代码运算效率的11个实用方法


      方法:速度, nrow(df)/time_taken = n 行每秒

      • 原始方法:1X, 856.2255行每秒(正则化为1)

      • 向量化方法:738X, 631578行每秒

      • 只考虑真值情况:1002X,857142.9行每秒

      • ifelse:1752X,1500000行每秒

      • which:8806X,7540364行每秒

      • Rcpp:13476X,11538462行每秒


      原文作者:Selva Prabhakaran

      译者:fibears


      【R】提升R代码运算效率的11个实用方法

      【R】提升R代码运算效率的11个实用方法

      点击“阅读原文”查看更多精彩内容


      测试结尾

      请关注“恒诺新知”微信公众号,感谢“R语言“,”数据那些事儿“,”老俊俊的生信笔记“,”冷🈚️思“,“珞珈R”,“生信星球”的支持!

      • 分享:
      作者头像
      weinfoadmin

      上一篇文章

      【工作帮】诚聘数据分析师/数据挖掘师
      2016年3月11日

      下一篇文章

      【R微课】14天用R做机器学习第一天
      2016年3月13日

      你可能也喜欢

      3-1665801675
      R语言学习:重读《R数据科学(中文版)》书籍
      28 9月, 2022
      6-1652833487
      经典铁死亡,再出新思路
      16 5月, 2022
      1-1651501980
      R语言学习:阅读《R For Everyone 》(第二版)
      1 5月, 2022

      搜索

      分类

      • R语言
      • TCGA数据挖掘
      • 单细胞RNA-seq测序
      • 在线会议直播预告与回放
      • 数据分析那些事儿分类
      • 未分类
      • 生信星球
      • 老俊俊的生信笔记

      投稿培训

      免费

      alphafold2培训

      免费

      群晖配置培训

      免费

      最新博文

      Nature | 单细胞技术揭示衰老细胞与肌肉再生
      301月2023
      lncRNA和miRNA生信分析系列讲座免费视频课和课件资源包,干货满满
      301月2023
      如何快速批量修改 Git 提交记录中的用户信息
      261月2023
      logo-eduma-the-best-lms-wordpress-theme

      (00) 123 456 789

      weinfoadmin@weinformatics.cn

      恒诺新知

      • 关于我们
      • 博客
      • 联系
      • 成为一名讲师

      链接

      • 课程
      • 事件
      • 展示
      • 问答

      支持

      • 文档
      • 论坛
      • 语言包
      • 发行状态

      推荐

      • iHub汉语代码托管
      • iLAB耗材管理
      • WooCommerce
      • 丁香园论坛

      weinformatics 即 恒诺新知。ICP备案号:粤ICP备19129767号

      • 关于我们
      • 博客
      • 联系
      • 成为一名讲师

      要成为一名讲师吗?

      加入数以千计的演讲者获得100%课时费!

      现在开始

      用你的站点账户登录

      忘记密码?

      还不是会员? 现在注册

      注册新帐户

      已经拥有注册账户? 现在登录

      close
      会员购买 你还没有登录,请先登录
      • ¥99 VIP-1个月
      • ¥199 VIP-半年
      • ¥299 VIP-1年
      在线支付 激活码

      立即支付
      支付宝
      微信支付
      请使用 支付宝 或 微信 扫码支付
      登录
      注册|忘记密码?