1

I have a long time series of a variable. I want to perform a backward moving average with window size of 20. If I keep this window size then the output series will be shortened by length 20 (I mean first 20 values will be NAs) but what I want is that the the output series should be of same length as original series with non NAs. For this, I want to vary the window size in the beginning so that I can get the desired output. For example, for the first 20 values in original time series, the moving window size can be 1, 2, 3, ...., 20, respectively. Then I want to keep the window size of 20 afterwards. How this can be done?

Here is the sample data and desired output with window size 3:

Days    Original_Values    Desired_Output
 1           2                  2
 2           4                  2
 3           1                  3
 4           3                  7/3
 5           5                  8/3
 6           6                  9/3
 7           4                  14/3
 8           9                  15/3
raghav
  • 533
  • 2
  • 11
  • 1
    This answer in particular should do the job: https://stackoverflow.com/a/26216635/ Let me know if you're still having trouble. – Ian Campbell Jan 06 '21 at 19:20
  • This answers my question to a great extent but I want the moving average of previous N (window size) values. The current day should be estimated by averaging previous N days. But the post you mention considers the current day in the calculation of moving average. Should I modify my question if It is not clear from my question? – raghav Jan 06 '21 at 19:32
  • Yes, I think it would be much improved by example data and expected output. – Ian Campbell Jan 06 '21 at 19:34

1 Answers1

1

Using the input shown reproducibly in the Note at the end, use rollapplyr specifying offsets -1, -2, -3 and use the argument partial=TRUE to let it use fewer than the specified offsets if only fewer are available. The first element cannot be calculated since there are no prior elements so for that specify that the first element be filled in using the fill argument.

library(zoo)

DF2 <- transform(DF, roll = 
  rollapplyr(Original, list(-(1:3)), mean, partial = TRUE, fill = Original[1]))

with(DF2, identical(Desired, roll))  # check that result matches Desired
## [1] TRUE

Note

Lines <- "
 Days        Original           Desired
 1           2                  2
 2           4                  2
 3           1                  3
 4           3                  7/3
 5           5                  8/3
 6           6                  9/3
 7           4                  14/3
 8           9                  15/3"
DF <- read.table(text = Lines, header = TRUE)
DF <- transform(DF, Desired = sapply(Desired, function(x) eval(parse(text = x))))
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341