tags:

views:

61

answers:

2

how dows this work in R...

I am using a package (zoo 1.6-4) that defines a S3 class for time series sets. I am writing a derived class where I want to override a few methods and can't get past this one:[.zoo!

in my derived class rows are indexed by timestamp, like in zoo, but differently from zoo, I allow only POSIXct values in the index. my users will be selecting columns all of the time, while slicing series only occasionally so I want to offer obj[name] instead of obj[, name].

my objects have class c("delftfews", "zoo").

but...

how do I override a method?

I tried this:

"[.delftfews" <- function(x, i, j, drop=TRUE, ...) {
  if (missing(i)) return(NextMethod())
  if (all(class(i) == "character") && missing(j)) {
    return(NextMethod('[', x=x, i=1:NROW(x), j=i, drop=drop, ...))
  }
  NextMethod()
}

but I get this error: Error in rval[i, j, drop = drop., ...] : incorrect number of dimensions.

I have solved by editing the source from zoo: I removed those ..., but I don't get why that works. anybody can explain what is going on here?

A: 

A point of clarification: allowing only POSIXct index values does not allow indexing columns by name only. I'm not sure how you arrived at that conclusion.

You're overriding zoo correctly, but I think you misunderstand NextMethod. The error is caused by if (missing(i)) return(NextMethod()), which calls [.zoo if i is missing, but [.zoo requires i because zoo's internal data structure is a matrix. Something like this should work:

if (missing(i)) i <- 1:NROW(x)

though I'm not sure if you have to explicitly pass this new i to NextMethod...

You may be interested in the xts package, if you haven't already taken a look at it.

Joshua Ulrich
I'm reserving POSIXct as type for indexing rows and character as type for indexing columns. seems to me a clear-cut distinction. why do you say the contrary?
mariotomo
as far as I can see, `[.zoo` does not require `i` nor `j`. the code for `[.zoo` already contains the same `if (missing(i)) i <- 1:NROW(x)`. if `i` is missing or is `NULL`, the whole column is returned. try something like `TS[, name]`. looks awkward, but works.
mariotomo
about `NextMethod`, more than "misunderstanding", I'm sure I'm not understanding its logic nor implementation nor suggested usage and my question is exactly about this. I have a fair though rusty theoretical compilers knowledge so I trust I can follow an explanation.
mariotomo
+2  A: 

The problem is that with the above definition of [.delftfews this code:

library(zoo)
z <- structure(zoo(cbind(a = 1:3, b = 4:6)), class = c("delftfews", "zoo"))
z["a"]
# generates this call: `[.zoo`(x = 1:6, i = 1:3, j = "a", drop = TRUE, z, "a")

Your code does work as is if you write the call like this:

z[j = "a"]
# generates this call: `[.zoo`(x = z, j = "a")

I think what you want is to change the relevant line in [.delftfews to this:

return(NextMethod(.Generic, object = x, i = 1:NROW(x), drop = drop))
# z["a"] now generates this call: `[.zoo`(x = z, i = 1:3, j = "a", drop = TRUE)
G. Grothendieck
thanks, this is what I understood from your -working- example: when invoking NextMethod, all parameters already specified stay specified in the order and form (named/unnamed) they were received. I can't override unnamed parameters and I don't need to repeat the `...`. I can override or fill in named parameters if I wish to do so. (also interesting the behaviour of `drop`: to have `[.zoo` use the default defined in `[.delftfews`, I must pass it as `drop=drop`). (`object` is named `object` even if one names it differently!). what is the role of that `.Generic`?
mariotomo
p.s.: the shortest still working version was: `NextMethod(i=1:NROW(x), drop=drop)`
mariotomo
.Generic equals `"["` in this case. `?NextMethod` mentions it and a few other similar ones. BTW, you might want to use `i = seq_len(NROW(x))` if its possible for `x` to have zero rows.
G. Grothendieck