理解R性能plyr - dply和因子变量

时间:2016-10-04 17:39:31

标签: r plyr

我的电脑是英特尔酷睿i7,12GB内存和Windows 10,只是为了给你一些背景信息。我正在尝试对数据框执行简单操作,数据框大约有 41K 条目,其大小为.csv格式大约为20MB。 数据框有4列:

  1. 地址:因素变量,大约 41K 不同级别(无重复级别)
  2. 阻止:因素变量,大约 39K 不同级别(大多数区块只有一个与之相关的地址,但其他区域最多有100个
  3. 能源:一个int变量
  4. 细分:因素变量只有 7 级别
  5. 让我向您展示dataFrame的summary()输出:

             Address            Block           ENERGY        Segment     
     BAC0602532301:    1   A33093097:  165   Min.   :      0   A   :11863  
     BAC0603557493:    1   B79083796:  165   1st Qu.:  48590   A+  : 7723  
     BAC0604416292:    1   A08721177:  158   Median :  75420   A++ : 3948  
     BAE0602962660:    1   A46581666:  153   Mean   : 144694   A+++: 2324  
     BAE0603336589:    1   B21053848:  138   3rd Qu.: 154167   B   : 8110  
     BAI0602739803:    1   A08119687:   89   Max.   :2802501   C   : 4051  
     (Other)      :40086   (Other)  :39224                     D   : 2073   
    

    现在,我要执行的操作是每个Block (大约有39K)选择 ENERGY 列的最大值和地址< / strong>和 Segement 与此 ENERGY 相关。

    所以要做到这一点,我知道有很多不同的选择。我通常尝试使用plyrdplyr包中的函数,因为我认为它们比Basic包的其他选项更快,特别是如果操作可以被认为是Split-Appy-Combine操作。 问题是,如果我从plyr包执行此操作:

     ddply(dataFrame, "Block", summarize, AddressMax =  Address[which.max(ENERGY)], SegmentMax = Segment[which.max(ENERGY)], EnergyMax = max(ENERGY))
    

    计算机永远不会结束,我必须最终杀死R程序

    如果我从dply包中执行此操作:

    Blocks <- group_by(DataFrame,Blocks)
    
    MaxsbyBlock <- summarise(Blocks, AdressMax = Address[which.max(ENERGY)], SegmentMax = Segment[which.max(ENERGY)], EnergyMax = max(ENERGY))
    

    完成需要大约30到40秒(至少它完成!!!)。

    否则,如果我放弃尝试使用 ddply 恢复地址,它会完美运行,实际上如果你执行此操作(注意现在AdressMax已经消失):

    ddply(dataFrame, "Block", summarize,SegmentMax = Segment[which.max(ENERGY)], EnergyMax = max(ENERGY))
    

    完成需要大约3到4秒。 ddply策略可以进一步提升。所以,有人可以告诉我,使用ddply或dply包来尝试恢复Adress Factor变量的值时会有什么问题吗?如果您使用__aggregate 功能和合并,它会更快,我想了解至少一点原因:

    aggdata<-aggregate(Energy~Blocks, data=dataFrame, max)
    merge(aggdata,dataFrame,by.x=c('Blocks','Energy'),by.y=c('Blocks','Energy'))
    

1 个答案:

答案 0 :(得分:2)

我注意到这个Q现在已经有5天未被回答或评论过了。

我没有解释为什么plyrdplyr方法没有按预期执行,但如果OP有兴趣解决潜在问题,则使用data.table有两种方法。

基准测试三种方法

使用下面创建的虚拟数据DT,正在对三种不同的方法进行基准测试:

  • base_agg_merge:使用Q
  • 中给出的基本函数进行聚合和合并
  • dt_agg_merge:使用data.table
  • 汇总和加入
  • dt_order_group:使用data.table
  • 订购和分组

来自Q的其他方法需要太多的运行时间(dplyr:22秒,plyr没有AddressMax:2.6秒)所以它们从{{1}中省略跑。

microbenchmark

最快的方法library(microbenchmark) library(data.table) microbenchmark( base_agg_merge = { aggdata <- aggregate(Energy ~ Block, data = DT, max) result1 <- merge(aggdata, DT, by = c("Block", "Energy")) }, dt_agg_merge = { temp <- DT[, .(max_Energy = max(Energy)), keyby = Block] result2 <- DT[temp, on = c("Block", Energy = "max_Energy")] }, dt_order_group = { result3 <- DT[order(-Energy), .SD[1], keyby = Block] }, times = 10 ) Unit: milliseconds expr min lq mean median uq max neval base_agg_merge 275.106516 279.646932 297.287758 281.229186 302.062803 395.936697 10 dt_agg_merge 7.527084 7.789126 9.489412 9.001351 9.342873 17.171266 10 dt_order_group 4.458858 5.437927 6.508181 6.784382 7.405881 8.685504 10 的工作原理如下:

  • dt_order_group排序(反转)
  • 分组Energy
  • 返回每组中的第一行

虽然Blockbase_agg_merge遵循相同的想法,但dt_agg_merge版本的速度提高了30倍:

  • 分组data.table
  • 每个小组获得Block
  • 合并max(Energy)Block(注意,这应该返回任何关系,即组中同一max_Energy的行)

基准测试是在装有Intel Core i5,8 GB RAM,使用R版本3.3.1的Windows 10和max_Energy的开发版本1.9.7(参见Installation instructions)上运行的

数据

OP提供了data.table基础数据,这对虚拟数据建模非常有帮助。

summary()

set.seed(1234) n <- 41000L m <- 10000L dataFrame <- data.frame( Address = factor(m + sample.int(n)), Block = factor(m + sample.int(39000L, n, replace = TRUE, prob = 1/seq_len(39000L))), Energy = as.integer(rlnorm(n, meanlog = 11)), Segment = factor(sample(LETTERS[1:7], n, replace = TRUE)) ) summary(dataFrame) ## Address Block Energy Segment ## 10001 : 1 10001 : 3714 Min. : 1294 A:5871 ## 10002 : 1 10002 : 1849 1st Qu.: 30579 B:5762 ## 10003 : 1 10003 : 1247 Median : 59730 C:5836 ## 10004 : 1 10004 : 905 Mean : 99107 D:5892 ## 10005 : 1 10005 : 719 3rd Qu.: 117060 E:5855 ## 10006 : 1 10006 : 584 Max. :2977127 F:5979 ## (Other):40994 (Other):31982 G:5805 除了所有列都是因素。