我有一个包含18列和11520行的data.frame(link to file),我将这样转换:
library(plyr)
df.median<-ddply(data, .(groupname,starttime,fPhase,fCycle),
numcolwise(median), na.rm=TRUE)
根据system.time(),运行需要很长时间:
user system elapsed
5.16 0.00 5.17
此调用是webapp的一部分,因此运行时间非常重要。有没有办法加快这个调用?
答案 0 :(得分:9)
只使用aggregate
要快得多......
> groupVars <- c("groupname","starttime","fPhase","fCycle")
> dataVars <- colnames(data)[ !(colnames(data) %in% c("location",groupVars)) ]
>
> system.time(ag.median <- aggregate(data[,dataVars], data[,groupVars], median))
user system elapsed
1.89 0.00 1.89
> system.time(df.median <- ddply(data, .(groupname,starttime,fPhase,fCycle), numcolwise(median), na.rm=TRUE))
user system elapsed
5.06 0.00 5.06
>
> ag.median <- ag.median[ do.call(order, ag.median[,groupVars]), colnames(df.median)]
> rownames(ag.median) <- 1:NROW(ag.median)
>
> identical(ag.median, df.median)
[1] TRUE
答案 1 :(得分:7)
总结一下评论中的一些要点:
plyr
主要是为了易用而不是为了提高性能而设计的(尽管最近的版本有一些不错的性能改进)。一些基本功能更快,因为它们具有更少的开销。 @JDLong指出a nice thread涵盖了其中一些问题,包括哈德利的一些专业技术。答案 2 :(得分:4)
计算中位数时数据的顺序很重要:如果数据的顺序从最小到最大,那么计算速度会快一些。
x <- 1:1e6
y <- sample(x)
system.time(for(i in 1:1e2) median(x))
user system elapsed
3.47 0.33 3.80
system.time(for(i in 1:1e2) median(y))
user system elapsed
5.03 0.26 5.29
对于新数据集,在导入数据时按适当的列对数据进行排序。对于现有数据集,您可以将它们排序为批处理作业(在Web应用程序之外)。
答案 3 :(得分:3)
添加Joshua的解决方案。如果您决定使用均值而不是中位数,则可以将计算速度提高4倍:
> system.time(ag.median <- aggregate(data[,dataVars], data[,groupVars], median))
user system elapsed
3.472 0.020 3.615
> system.time(ag.mean <- aggregate(data[,dataVars], data[,groupVars], mean))
user system elapsed
0.936 0.008 1.006
答案 4 :(得分:3)
使用dplyr:
可以更快地处理这些数据library(dplyr)
system.time({
data %>%
group_by(groupname, starttime, fPhase, fCycle) %>%
summarise_each(funs(median(., na.rm = TRUE)), inadist:larct)
})
#> user system elapsed
#> 0.391 0.004 0.395
(你需要dplyr 0.2来获得%>%
和summarise_each
)
这比plyr更有利:
library(plyr)
system.time({
df.median <- ddply(data, .(groupname, starttime, fPhase, fCycle),
numcolwise(median), na.rm = TRUE)
})
#> user system elapsed
#> 0.991 0.004 0.996
和aggregate()
(来自@ joshua-ulrich的代码)
groupVars <- c("groupname", "starttime", "fPhase", "fCycle")
dataVars <- colnames(data)[ !(colnames(data) %in% c("location", groupVars))]
system.time({
ag.median <- aggregate(data[,dataVars], data[,groupVars], median)
})
#> user system elapsed
#> 0.532 0.005 0.537
答案 5 :(得分:2)
我只是使用标准库函数(例如,'table','tapply','aggregate'等)对大型数据框(plyr包中的棒球数据集)进行了一些简单的转换。类似的plyr函数 - 在每种情况下,我发现plyr明显更慢。如,
> system.time(table(BB$year))
user system elapsed
0.007 0.002 0.009
> system.time(ddply(BB, .(year), 'nrow'))
user system elapsed
0.183 0.005 0.189
其次,我确实不调查这是否会提高您的性能,但对于您现在正在使用的大小的数据框架,我使用 {{3 库,可在CRAN上使用。创建data.table对象以及将现有的data.frames转换为data.tables很简单 - 只需在要转换的data.frame上调用data.table:
dt1 = data.table(my_dataframe)