Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Apply family of functions on mts objects

Tags:

r

apply

Using apply (or sapply) on an mts object removes its time series properties when sending to function. How should I apply same function (with ts input and ts output) on each of times series in an mts object and return it (preferably as mts) [I mean besides using for loops]?

For example suppose I write a function that returns the trend of a time series (using stl)

myfunc <- function(x) {
      return(stl(x,"per")$time.series[,2])
}

Now for a sample mts

z <- ts(matrix(rnorm(90), 30, 3), start=c(1961, 1), frequency=4)
class(z)

Sending only one of the time series works correct:

myfunc(z[,1]) # works correctly, returns the trend of first series

My function is not designed for multiple time series so:

myfunc(z) # will not work returning the error below

Error in stl(x, "per") : only univariate series are allowed

Using apply on the mts object send each of the time series as a vector, not preserving its time series properties (tsp):

apply(z,2,myfunc) # will not work returning the error below

Error in stl(x, "per") : 
series is not periodic or has less than two periods
like image 314
Majid Einian Avatar asked Nov 27 '12 12:11

Majid Einian


2 Answers

A simple way around this, is to work with the indices instead of a clean apply :

sapply(seq_len(ncol(z)),function(i) myfunc(z[,i]))

apply puts clean vectors inside the function, because it first converts an object to a matrix. By using the [ function defined for time series objects, you are sure that you extract a valid time series each time.

like image 181
Joris Meys Avatar answered Nov 03 '22 20:11

Joris Meys


I change the myfunc to check if it have a ts object as parameter x.

If x is not a ts , it is converted to ts object as stl need this parameter type.

  myfunc <- function(x,...){
        y <- x
       if(class(x) != 'ts') {
         dots <- c(...)
         y <- ts(x,start=c(dots[1], dots[2]), frequency=dots[3])
       }
       return(stl(y,"per")$time.series[,2])
     }
  ## no need to conversion (already ts object)
  myfunc(z[,1])


  ## mts object ( here we give parameter necessary for conversion)
  apply(z,2,myfunc,1961,1,4) 
like image 30
agstudy Avatar answered Nov 03 '22 19:11

agstudy