1

我的数据是 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每个的滚动平均值。ID我使用以下方法执行此操作:

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])
  }
}

但是,我现在需要计算 1 到 10 分钟的滚动时间。我可以通过使用上面的代码并替换为以下行来做到这一点:

for ( i in seq(6000, 60000, by = 6000)) {

但是,这需要数小时才能运行我的数据集,并导致我的 Mac 上的 RStudio(详情如下)挂起!有没有办法a)整理上面的代码或b)使用不同的包/方法来实现更快的结果?

谢谢你。

R version 3.2.3 (2015-12-10)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.10.5 (Yosemite)

locale:
[1] en_AU.UTF-8/en_AU.UTF-8/en_AU.UTF-8/C/en_AU.UTF-8/en_AU.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] zoo_1.7-12  dplyr_0.4.3

loaded via a namespace (and not attached):
 [1] lazyeval_0.1.10 magrittr_1.5    R6_2.1.1        assertthat_0.1  parallel_3.2.3  DBI_0.3.1      
 [7] tools_3.2.3     Rcpp_0.12.2     grid_3.2.3      lattice_0.20-33
4

2 回答 2

3

它运行缓慢的原因是

  1. 问题中的代码已经破坏了通过分配给变量并传递该变量rollapply来检测mean正在传递的能力。mean(在 的情况下meanrollapply调用rollmean包含针对该情况的优化代码)。如果问题中的代码mean直接通过或使用rollmean它会大大加快速度。

  2. filter不删除 NA,因此对于苹果对苹果的比较,不应该在. 如果您确实使用它,那么它也会破坏优化。 na.rm = TRUErollapply

例如,在这个比较中,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数据长度和其他方面而有所不同,因为这只是一个测试。

于 2016-03-14T15:19:32.403 回答
1

我不确定您是否考虑过其他汇总函数,但至少就平均而言,您可以rollapply通过使用来加速该函数filtertransmute(stats::filter(Acceleration,rep(1/i,i),sides=1))

(在此处查看其他选项:计算 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 秒,但这取决于您的计算机有多少内核。

于 2016-03-14T01:01:51.293 回答