我的数据是988,785 obs。 3个变量。我的数据的一个较小的例子如下:
Names <- c("Jack", "Jill", "John")
RawAccelData <- data.frame(
Sample = as.numeric(rep(1:60000, each = 3)),
Acceleration = rnorm(6000),
ID = rep((Names), each = 60000)
)
我的设备采样率为100 Hz。我希望在1到10秒的时间内计算每个Acceleration
的{{1}}的滚动平均值。我使用以下内容执行此操作:
ID
但是,我现在需要计算1到10分钟的滚动时间。我可以通过使用上面的代码并用以下代码替换:
require(dplyr)
require(zoo)
for (summaryFunction in c("mean")) {
for ( i in seq(100, 1000, by = 100)) {
tempColumn <- RawAccelData %>%
group_by(ID) %>%
transmute(rollapply(Acceleration,
width = i,
FUN = summaryFunction,
align = "right",
fill = NA,
na.rm = T))
colnames(tempColumn)[2] <- paste("Rolling", summaryFunction, as.character(i), sep = ".")
RawAccelData <- bind_cols(RawAccelData, tempColumn[2])
}
}
但是,这需要几个小时来运行我的数据集并导致我的Mac上的RStudio(下面的详细信息)挂起!有没有办法可以a)整理上面的代码或b)使用不同的包/方法来实现更快的结果?
谢谢。
for ( i in seq(6000, 60000, by = 6000)) {
答案 0 :(得分:3)
它运行缓慢的原因是
问题中的代码通过将rollapply
分配给变量并传递该变量,使mean
无法检测到mean
被传递的能力。 (对于mean
,rollapply
调用rollmean
,其中包含针对该情况的优化代码)。如果问题中的代码直接通过mean
或者使用rollmean
,那么它的速度会快得多。
filter
不会删除NAs,因此对于苹果与苹果的比较,应该 在na.rm = TRUE
中使用rollapply
。如果您确实使用它,那么它也将失败优化。
例如,在此比较中,rollapply
的运行速度是filter
的两倍以上:
library(zoo)
library(rbenchmark)
set.seed(123)
r <- rnorm(10000)
benchmark(filter = stats::filter(r, rep(1/100,100), sides = 1),
rollapply = rollapplyr(r, 100, mean, fill = NA))[1:4]
,并提供:
test replications elapsed relative
1 filter 100 3.75 2.119
2 rollapply 100 1.77 1.000
当然,速度可能会根据width
,数据长度和输入的其他方面而有所不同,因为这只是一次测试。
答案 1 :(得分:1)
我不确定您是否还有其他摘要功能,但至少在平均值上,您可以使用rollapply
来加速filter
功能:
transmute(stats::filter(Acceleration,rep(1/i,i),sides=1))
(请参阅此处的其他选项:Calculating moving average in R)使用system.time
,这会让我从117秒加速到4秒!!
您还可以并行执行一些for
循环。
而不是
for ( i in seq(6000, 60000, by = 6000)) {
尝试:
library(parallel)
for (summaryFunction in c("mean")) {
rollCols = mclapply (seq(100, 1000, by = 100),function(i){
tempColumn <- RawAccelData %>%
group_by(ID) %>%
transmute(stats::filter(Acceleration,rep(1/i,i),sides=1))
colnames(tempColumn)[2] <- paste("Rolling", summaryFunction, as.character(i), sep = ".")
return(tempColumn[2])
})
}
RawAccelData = cbind(RawAccelData,do.call(cbind,rollCols))
这使我从72秒加速到40秒,但这取决于你的计算机有多少核心。