我的电脑是英特尔酷睿i7,12GB内存和Windows 10,只是为了给你一些背景信息。我正在尝试对数据框执行简单操作,数据框大约有 41K 条目,其大小为.csv
格式大约为20MB。
数据框有4列:
让我向您展示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 相关。
所以要做到这一点,我知道有很多不同的选择。我通常尝试使用plyr
或dplyr
包中的函数,因为我认为它们比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'))
答案 0 :(得分:2)
我注意到这个Q现在已经有5天未被回答或评论过了。
我没有解释为什么plyr
和dplyr
方法没有按预期执行,但如果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
虽然Block
和base_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
除了所有列都是因素。