[R] Generic 'diff'

Wacek Kusnierczyk Waclaw.Marcin.Kusnierczyk at idi.ntnu.no
Tue May 19 10:23:52 CEST 2009

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, ...)
    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])
        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:

    # 1 1 1

    difff(1:4, fun=`+`)
    # 3 5 7

it might be useful if the original diff were working this way.


More information about the R-help mailing list