tags:

views:

188

answers:

3

I would like to program a time series class. The idea is that I instantiate an object with an expression and some other time series objects, for instance

(two time series)
x <- ts(rnorm(10), frequency = 4, start = c(1959, 2))
y <- ts(rnorm(10), frequency = 4, start = c(1959, 2))

(a time series, defined to be the sum of x and y)
z <- exprTs("x+y", parents=list(x=x, y=y))

(get some part of the series)
window(z, start=1960, end=1960.75)

The problem is, how can I evaluate the expression? I tried the following:

(constructor for class)
exprTs <- function(expr, parents) {
res = list(expr=expr, parents=parents)
class(res) <- "exprTs"
res
}

(window method)
window.exprTs <- function(z, ...) {
eval(substitute(z$expr, lapply(z$parents, window, ...)))
#do.call(z$expr, lapply(z$parents, window, ...))
}

I can not get the window method to work.

If you could guide me to how to use substitute, eval, do.call appropriately, that would be very helpful.

A: 

One problem is that you are specifying the expression as a string so it will be evaluated into a string. If you want to parse a string into an expression, you need to use the parse command:

> "x+y"
[1] "x+y"
> parse(text="x+y")
expression(x+y)
attr(,"srcfile")
<text> 

But yeah, why not use apply and functions instead?

Jonathan Chang
I still do not get it right.substitute(parse(text="x+y"), list(x=x, y=y)) seems not the right command to produce the sum.
Karsten W.
Why are you trying to substitute rather than evaluate the expression? `eval(parse(text="x+y"))`.
Jonathan Chang
+1  A: 

You may be thinking about this in the wrong way and just over-complicate things. There is already an addition defined for ts objects:

R> set.seed(42)
R> x <- ts(rnorm(10), frequency = 4, start = c(1959, 2))
R> y <- ts(rnorm(10), frequency = 4, start = c(1959, 2))
R> z <- x + y
R> cbind(x,y,z)
               x       y       z
1959 Q2  1.37096  1.3049  2.6758
1959 Q3 -0.56470  2.2866  1.7219
1959 Q4  0.36313 -1.3889 -1.0257
1960 Q1  0.63286 -0.2788  0.3541
1960 Q2  0.40427 -0.1333  0.2709
1960 Q3 -0.10612  0.6360  0.5298
1960 Q4  1.51152 -0.2843  1.2273
1961 Q1 -0.09466 -2.6565 -2.7511
1961 Q2  2.01842 -2.4405 -0.4220
1961 Q3 -0.06271  1.3201  1.2574
R> 

You don't really need an expression parser to operate on R objects.

Dirk Eddelbuettel
Is it possible to define a function on the fly, likez <- do.call(make.function(x+y), list(x=x, y=y))I would like to delay the calculation of the sum.
Karsten W.
ok, I found out about do.call("+", list(x=x,y=y)). Still thinking about using more then two input series..
Karsten W.
In response to defining a function on the fly, you mean just `function(x, y) { x + y }` ?
Jonathan Chang
A: 

Now I found a solution:

window.exprTs <- function(z, ...) {
names(z$parents)<-NULL
do.call(z$expr, lapply(z$parents, window, ...))
}

plus <- function(x, ...) if (nargs() == 1) x else x + Recall(...)
z <- exprTs(plus, parents=list(x=x, y=y))

Now
window(z, start=1960, end=1960.75)
gives the desired result.

Karsten W.
Would something like this be easier? window <- function(f, ...) { Reduce(f, list(...)) } x <- rnorm(10) ; y <- rnorm(10) ; z <- rnorm(10) window("+", x, y, z) [1] 2.0518301 2.3578890 -1.4470385 0.1740018 -0.5145332 - 1.1365355 [7] 1.2252515 1.2743573 -0.1090204 2.1623625
Jonathan Chang
Thanks for bringing this function Reduce to my attention!
Karsten W.