[R] Generic 'diff'

Gabor Grothendieck ggrothendieck at gmail.com
Tue May 19 14:38:29 CEST 2009


Note that this could be done like this for ordinary
vectors:

> x <- seq(1:4)^2

> apply(embed(x, 2), 1, function(x, f) f(rev(x)), f = diff)
[1] 3 5 7
> apply(embed(x, 2), 1, function(x, f) f(rev(x)), f = sum)
[1]  5 13 25

or a method to rollapply in zoo could be added for ordinary vectors.
Here it is applied to zoo objects:

> library(zoo)
> rollapply(zoo(x), 2, diff)
1 2 3
3 5 7
> rollapply(zoo(x), 2, sum)
 1  2  3
 5 13 25


On Tue, May 19, 2009 at 4:23 AM, Wacek Kusnierczyk
<Waclaw.Marcin.Kusnierczyk at idi.ntnu.no> wrote:
> Stavros Macrakis wrote:
>> On Mon, May 18, 2009 at 6:00 PM, Gabor Grothendieck <ggrothendieck at gmail.com
>>
>>> wrote:
>>>
>>
>>
>>> I understood what you were asking but R is an oo language so
>>> that's the model to use to do this sort of thing.
>>>
>>>
>>
>> I am not talking about creating a new class with an analogue to the
>> subtraction function.  I am talking about a function which applies another
>> function to a sequence and its lagged version.
>>
>> Functional arguments are used all over the place in R's base package
>> (Xapply, sweep, outer, by, not to mention Map,  Reduce, Filter, etc.) and
>> they seem perfectly natural here.
>>
>
> perhaps 'diff' would not be the best name, something like 'lag' would be
> better for the more generic function, but 'lag' is already taken.
>
> i agree it would be reasonable to have diff (lag) to accept an extra
> argument for the function to be applied.  the solution of wrapping the
> vector into a new class to be diff'ed with a non-default diff does not
> seem to make much sense, as (a) what you seem to want is to custom-diff
> plain vectors, (b) to keep the diff family coherent, you'd need to
> upgrade the other diffs to have the extra argument anyway.
>
> as you say, it's trivial to implement an extended diff, say difff,
> reusing code from diff:
>
>    difff = function(x, ...)
>       UseMethod('difff')
>    difff.default = function(x, lag=1, differences=1, fun=`-`, ...) {
>       ismat = is.matrix(x)
>       xlen = if (ismat) dim(x)[1L] else length(x)
>    if (length(lag) > 1L || length(differences) > 1L || lag < 1L ||
> differences < 1L)
>       stop("'lag' and 'differences' must be integers >= 1")
>    if (lag * differences >= xlen) return(x[0])
>    r = unclass(x)
>    i1 = -1L:-lag
>    if (ismat)
>        for (i in 1L:differences)
>            r = fun(r[i1, , drop = FALSE], r[-nrow(r):-(nrow(r) - lag +
> 1), , drop = FALSE])
>    else
>        for (i in 1L:differences) r = fun(r[i1],
> r[-length(r):-(length(r) - lag + 1)])
>    class(r) = oldClass(x)
>    r }
>
> now, this naive version seems to work close to what you'd like:
>
>    difff(1:4)
>    # 1 1 1
>
>    difff(1:4, fun=`+`)
>    # 3 5 7
>
> it might be useful if the original diff were working this way.
>
> vQ
>




More information about the R-help mailing list