我有这个金融交易数据集,它非常大但足够小,可以留在内存中。
R> str(trans)
'data.frame': 130000000 obs. of 5 variables:
$ id : int 5 5 5 5 6 11 11 11 11 11 ...
$ kod : int 2 3 2 3 38 2 3 6 7 6 ...
$ ar : int 329 329 330 330 7 329 329 329 329 329 ...
$ belopp: num 1531 -229.3 324 -48.9 0 ...
$ datum : int 36976 36976 37287 37287 37961 36976 36976 37236 37236 37281 ...
我需要循环遍历它,为每个唯一ID提取事务,然后进行一堆计算。麻烦的是数据集的子集太慢了。
R> system.time(
+ sub <- trans[trans$id==15,]
+ )
user system elapsed
7.80 0.55 8.36
R> system.time(
+ sub <- subset(trans, id == 15)
+ )
user system elapsed
8.49 1.05 9.53
由于此数据集中有大约10米的唯一ID,这样的循环会花费很长时间,任何想法如何加快它的速度?
修改 我已经涉足了'data.tables',索引和排序并没有太多运气......
library(data.table)
trans2 <- as.data.table(trans)
trans2 <- trans2[order(id)]
trans2 <- setkey(trans2, id)
R> system.time(
+ sub <- trans2[trans2$id==15,]
+ )
user system elapsed
7.33 1.08 8.41
R> system.time(
+ sub <- subset(trans2, id == 15)
+ )
user system elapsed
8.66 1.12 9.78
EDIT2 太棒了。
R> system.time(
+ sub <- trans2[J(15)]
+ )
user system elapsed
0 0 0
答案 0 :(得分:3)
Note:
通过将正在计算的函数从rowSums
更改为colSums
(在data.table的情况下使用lapply
)来编辑帖子。
我认为你不能比data.table
更快地得到结果。这是plyr
和data.table
之间的基准。当然,如果耗时的部分是您的功能,那么您可以使用doMC
并行使用plyr
(假设您有很多核心或您在群集上工作)。否则,我会坚持data.table
。这是一个包含大量测试数据和虚拟函数的分析:
# create a huge data.frame with repeating id values
len <- 1e5
reps <- sample(1:20, len, replace = TRUE)
x <- data.frame(id = rep(1:len, reps))
x <- transform(x, v1 = rnorm(nrow(x)), v2 = rnorm(nrow(x)))
> nrow(x)
[1] 1048534 # 1 million rows
# construct functions for data.table and plyr
# method 1
# using data.table
DATA.TABLE <- function() {
require(data.table)
x.dt <- data.table(x, key="id")
x.dt.out <- x.dt[, lapply(.SD, sum), by=id]
}
# method 2
# using plyr
PLYR <- function() {
require(plyr)
x.plyr.out <- ddply(x, .(id), colSums)
}
# let's benchmark
> require(rbenchmark)
> benchmark(DATA.TABLE(), PLYR(), order = "elapsed", replications = 1)[1:5]
test replications elapsed relative user.self
1 DATA.TABLE() 1 1.006 1.00 .992
2 PLYR() 1 67.755 67.351 67.688
在包含100万行的data.frame上,data.table
需要0.992 seconds
。使用data.table
与plyr
进行比较的速度(无可否认,计算列总和)为68x
。根据功能的计算时间,这种加速会有所不同。但data.table
仍然会更快。 plyr
是一种拆分 - 应用 - 合并策略。与使用基础分割,应用和组合自己相比,我认为你不会获得类似的加速。当然你可以尝试一下。
我运行了1000万行的代码。 data.table
在5.893秒内跑了。 plyr
花了6300秒。
答案 1 :(得分:0)
为什么不使用拆分,应用和合并策略?
这样的事情(没有样本数据我不知道这是否有用):
fastsplit <- function (df) {
lista <- split(seq(nrow(df)), df$id)
return(lista)
}
# function to split the data frame into a list by id
lista_split <- fastsplit(trans)
# now, assuming that one of the calculations is, for instance, to sum belopp
# apply the function to each subset
result1 <- lapply(lista_split, function(.indx){
sum_bellop = sum(trans$belopp[.indx])})
# combine stage
r1 <- do.call(rbind, result1)
提供上面的代码之后,我说如果你可以使用SQL会更快更容易。也许包sqldf可以帮到你吗?我从来没有试过它。我不知道它是否很快。 SQL中的代码非常简单。要像上面的R代码一样,只需使用类似的东西:
select id
, sum(belopp) as sum_bellop from trans
group by id
这将返回一个包含两列的表,id和belopp by id
的总和