2016-08-12 131 views
2

在R中,我試圖用不同的窗口寬度做一個很大的向量(最多400k個元素)的非常快的滾動平均值,然後對每個窗口寬度總結每年最大的數據。下面的例子有望清楚。 我已經嘗試了幾種方法,並且最快到現在似乎是使用來自包RcppRollroll_mean作爲運行平均值,並且aggregate用於選擇最大值。 請注意,內存需求是一個問題:下面的版本需要很少的內存,因爲它一次只執行一次滾動均值和聚合;這是首選。快速滾動平均值+總結

#Example data frame of 10k measurements from 2001 to 2014 
n <- 100000 
df <- data.frame(rawdata=rnorm(n), 
       year=sort(sample(2001:2014, size=n, replace=TRUE)) 
       ) 

ww <- 1:120 #Vector of window widths 

dfsumm <- as.data.frame(matrix(nrow=14, ncol=121)) 
dfsumm[,1] <- 2001:2014 
colnames(dfsumm) <- c("year", paste0("D=", ww)) 

system.time(for (i in 1:length(ww)) { 
    #Do the rolling mean for this ww 
    df$tmp <- roll_mean(df$rawdata, ww[i], na.rm=TRUE, fill=NA) 
    #Aggregate maxima for each year 
    dfsumm[,i+1] <- aggregate(data=df, tmp ~ year, max)[,2] 
}) #28s on my machine 
dfsumm 

這得到所需的輸出:一個data.frame 15行(年2001至15年),幷包含用於每個WW最大120個色譜柱(窗口寬度)和每年。

但是,計算仍然需要很長時間(因爲我必須計算數以千計的這些數據)。我嘗試過使用其他選項,即dplyrdata.table,但由於缺乏對這些軟件包的瞭解,我一直無法找到更快的東西。

這將是最快的方式來做到這一點,使用單個核心(該代碼已經在其他地方並行)?

回答

7

內存管理,即分配和複製,正在使用你的方法來扼殺你。

這裏是一個data.table方法,它通過參考分配:

library(data.table) 
setDT(df) 
alloc.col(df, 200) #allocate sufficient columns 

#assign rolling means in a loop 
for (i in seq_along(ww)) 
    set(df, j = paste0("D", i), value = roll_mean(df[["rawdata"]], 
             ww[i], na.rm=TRUE, fill=NA)) 

dfsumm <- df[, lapply(.SD, max, na.rm = TRUE), by = year] #aggregate 
+1

哇!我有一個簡單的10倍加速,不能更快樂。非常感謝! – AF7

-1

您創建的一個性能問題是使用cbind動態增長矢量。您可以嘗試預先分配預期的大小,然後使用dfsumm[x] <- y填充它。

+0

我想剛纔下面你的建議(見上文編輯的代碼),但並沒有真正看到任何改善。使用100k樣本的時間仍然是28s。 – AF7