[R] using "rollapply" to calculate a moving sum or running sum?
Enrico Schumann
es at enricoschumann.net
Sat Aug 3 13:16:18 CEST 2013
On Fri, 02 Aug 2013, Anika Masters <anika.masters at gmail.com> writes:
> This is not critical, but I am curious to learn. Are there any
> suggestions for speeding up the process to calculate a moving row sum?
> (Ideally from within R, as opposed to suing C, etc.)
> Using rollapply on a matrix of 45,000 rows and 400 columns takes 83 minutes.
>
> date()
> mymatrix <- matrix(data=1:45000, nrow=45000, ncol=400)
> temp <- t(rollapply(t(mymatrix), width=12, FUN=sum, by.column=T,
> fill=NA, partial=FALSE, align="left"))
> date()
>
Write a function that *quickly* computes the moving sum of a single row;
then loop over the rows.
Here is such a function, which is a slightly modified copy of the
function MA ("moving average") in the NMOF package.
rsum <- function (y, order, pad = NULL) {
n <- length(y)
ma <- cumsum(y)
ma[order:n] <- ma[order:n] - c(0, ma[1L:(n - order)])
if (!is.null(pad) && order > 1L)
ma[1L:(order - 1L)] <- pad
ma
}
The main 'trick' is the use of 'cumsum'. Some speed comparions can
given here
require("NMOF")
showExample("fastMA")
The original function computes a moving average but is "right-aligned"
(which I typically want for time series). Since in your example you use
'align = "left"', I flip the columns of your matrix left to right.
Your example (increase the size by increasing rows/cols):
require("zoo")
## data
rows <- 450
cols <- 40
mymatrix <- matrix(data = rnorm(rows*cols), nrow = rows, ncol = cols)
## with rollapply
temp <- t(rollapply(t(mymatrix), width=12, FUN=sum, by.column=T,
fill=NA, partial=FALSE, align="left"))
## with rsum
answer <- array(NA, dim = dim(mymatrix))
flipped <- mymatrix[ ,cols:1]
for (i in seq_len(rows))
answer[i, ] <- rsum(flipped[i, ], 12, NA)
all.equal(unname(temp), answer[ ,cols:1])
Regards,
Enrico
> On Thu, Jun 27, 2013 at 2:41 PM, arun <smartpink111 at yahoo.com> wrote:
>> Hi,
>> Try:
>> library(zoo)
>>
>> rollapply(t(mymatrix),width=12,FUN=sum,by.column=T,fill=NA,partial=FALSE,align="left")
>> # [,1] [,2] [,3] [,4] [,5]
>> #[1,] 342 354 366 378 390
>> #[2,] 402 414 426 438 450
>> #[3,] 462 474 486 498 510
>> #[4,] 522 534 546 558 570
>> #[5,] 582 594 606 618 630
>> #[6,] 642 654 666 678 690
>> #[7,] 702 714 726 738 750
>> #[8,] 762 774 786 798 810
>> #[9,] 822 834 846 858 870
>> #[10,] NA NA NA NA NA
>> #[11,] NA NA NA NA NA
>> #[12,] NA NA NA NA NA
>> #[13,] NA NA NA NA NA
>> #[14,] NA NA NA NA NA
>> #[15,] NA NA NA NA NA
>> #[16,] NA NA NA NA NA
>> #[17,] NA NA NA NA NA
>> #[18,] NA NA NA NA NA
>> #[19,] NA NA NA NA NA
>> #[20,] NA NA NA NA NA
>> A.K.
>>
>>
>>
>> ----- Original Message -----
>> From: Anika Masters <anika.masters at gmail.com>
>> To: R help <r-help at r-project.org>
>> Cc:
>> Sent: Thursday, June 27, 2013 3:00 PM
>> Subject: [R] using "rollapply" to calculate a moving sum or running sum?
>>
>> #using "rollapply" to calculate a moving sum or running sum?
>>
>> #I am tryign to use rollapply to calcualte a moving sum? #I tried
>> rollapply and get the error message
>> #"Error in seq.default(start.at, NROW(data), by = by) :
>> # wrong sign in 'by' argument"
>>
>> #example:
>>
>> mymatrix <- ( matrix(data=1:100, nrow=5, ncol=20) )
>> mymatrix_cumsum <- ( matrix(data=NA, nrow=5, ncol=20) )
>> w=12
>> for(i in 1: (ncol(mymatrix)-w+1) ) {
>> mymatrix_cumsum[ , i] <- apply(X=mymatrix[, i:(i+w-1)] , MARGIN=1,
>> FUN=sum, na.rm=T)
>> }
>>
>> #How might I use the "rollapply" function instead?
>>
>> rollapply(mymatrix, 12, sum)
>>
>> rollapply(data = mymatrix, width = 12, FUN=sum, by.column =T, fill =
>> NA, partial = FALSE, align = "left" )
>>
--
Enrico Schumann
Lucerne, Switzerland
http://enricoschumann.net
More information about the R-help
mailing list