2013-08-07 21 views
6

Tôi thường xuyên tìm thấy những thứ lăn của chuỗi thời gian (đặc biệt có nghĩa là) và ngạc nhiên khi thấy rằng rollmean đáng chú ý là nhanh hơn rollapply và phương pháp align = 'right' nhanh hơn các trình bao bọc rollmeanr.Điều gì khiến cho rollmean nhanh hơn rollapply (mã khôn ngoan)?

Chúng đạt được tốc độ này như thế nào? Và tại sao một người mất một số khi sử dụng trình bao bọc rollmeanr()?

Một số nền: Tôi đã sử dụng rollapplyr(x, n, function(X) mean(X)), tuy nhiên gần đây tôi đã xảy ra khi một vài ví dụ sử dụng rollmean. Các tài liệu đề xuất rollapplyr(x, n, mean) (lưu ý không có function một phần của đối số) sử dụng rollmean vì vậy tôi không nghĩ rằng sẽ có nhiều khác biệt về hiệu suất, tuy nhiên rbenchmark tiết lộ sự khác biệt đáng chú ý.

require(zoo) 
require(rbenchmark) 

x <- rnorm(1e4) 
r1 <- function() rollapplyr(x, 3, mean) # uses rollmean 
r2 <- function() rollapplyr(x, 3, function(x) mean(x)) 
r3 <- function() rollmean(x, 3, na.pad = TRUE, align = 'right') 
r4 <- function() rollmeanr(x, 3, align = "right") 

bb <- benchmark(r1(), r2(), r3(), r4(), 
      columns = c('test', 'elapsed', 'relative'), 
      replications = 100, 
      order = 'elapsed') 

print(bb) 

Tôi rất ngạc nhiên khi thấy rằng rollmean(x, n, align = 'right') là đáng chú ý nhanh hơn - và ~ 40x nhanh hơn so với cách tiếp cận rollapply(x, n, function(X) mean(X)) tôi.

test elapsed relative 
3 r3() 0.74 1.000 
4 r4() 0.86 1.162 
1 r1() 0.98 1.324 
2 r2() 27.53 37.203 

Sự khác biệt dường như lớn hơn khi kích thước tập dữ liệu tăng lên. Tôi chỉ thay đổi kích thước của x (thành rnorm(1e5)) trong mã ở trên và chạy lại thử nghiệm và thậm chí còn có sự khác biệt lớn hơn giữa các hàm.

test elapsed relative 
3 r3() 13.33 1.000 
4 r4() 17.43 1.308 
1 r1() 19.83 1.488 
2 r2() 279.47 20.965 

và cho x <- rnorm(1e6)

test elapsed relative 
3 r3() 44.23 1.000 
4 r4() 54.30 1.228 
1 r1() 65.30 1.476 
2 r2() 2473.35 55.920 

Làm thế nào có họ làm điều này? Ngoài ra, đây có phải là giải pháp tối ưu không? Chắc chắn, điều này nhanh nhưng có cách nào thậm chí nhanh hơn cách để thực hiện việc này không?

(Lưu ý: nói chung chuỗi thời gian của tôi là hầu như luôn luôn xts đối tượng - không vấn đề này?)

+2

bạn có thể muốn thử 'runmean' từ' caTools' để có kết quả nhanh hơn nhiều – eddi

+2

@DWIN tôi đã đọc trang trợ giúp. Tôi thấy văn bản bạn trích dẫn trong '? Rollapplyr' nhưng nó không giải thích tại sao. Tiếp theo tôi đã đi đến '? Rollmean' và tìm thấy" Những hàm này tính toán các phương tiện lăn, tối đa và trung bình tương ứng và do đó tương tự như 'cuộn tròn' nhưng được tối ưu hóa cho tốc độ "... cũng không giải thích tại sao. Ngoài ra, không giải thích tại sao 'rollmean (x, n, align = 'right')' nhanh hơn 'rollmeanr (x, n)'. Cuối cùng, không điều nào trong số này giải thích lý do tại sao khoảng trống hiệu suất phát triển với kích thước của dữ liệu. – ricardo

+0

Điều gì tạo thành một lời giải thích đầy đủ cho "tại sao"? Làm thế nào là "cần cho tốc độ" không phải là câu trả lời? –

Trả lời

7

Đang tính toán cán có nghĩa là nhanh hơn so với tính toán một hàm lăn nói chung, bởi vì thứ nhất là dễ dàng hơn để tính toán. Khi tính toán một hàm lăn nói chung bạn phải tính toán các chức năng trên mỗi cửa sổ một lần nữa và một lần nữa, mà bạn không cần phải làm cho mean, bởi vì bản sắc đơn giản:

(a2 + a3 + ... + an)/(n-1) = (a1 + a2 + ... + a(n-1))/(n-1) + (an - a1)/(n-1) 

và bạn có thể thấy đó là đòn bẩy bằng cách xem getAnywhere(rollmean.zoo).

Nếu bạn muốn có tốc độ quay nhanh hơn, hãy sử dụng runmean từ caTools, được triển khai trong C khiến cho nó nhanh hơn nhiều (nó cũng tốt hơn rất nhiều vì kích thước dữ liệu tăng nhanh hơn).

library(microbenchmark) 
library(caTools) 
library(zoo) 

x = rnorm(1e4) 
microbenchmark(runmean(x, 3, endrule = 'trim', align = 'right'), 
       rollmean(x, 3, align = 'right')) 
#Unit: microseconds 
#            expr  min  lq  median  uq  max neval 
# runmean(x, 3, endrule = "trim", align = "right") 631.061 740.0775 847.5915 1020.048 1652.109 100 
#     rollmean(x, 3, align = "right") 7308.947 9155.7155 10627.0210 12760.439 16919.092 100 
+0

Ngoài ra còn có 'TTR :: runMean', hoạt động tốt với các đối tượng xts. –

Các vấn đề liên quan