Message-ID: <971536df0905190538r1c4d7eb8yf44fefff5fe8842f@mail.gmail.com>
Date: 2009-05-19T12:38:29Z
From: Gabor Grothendieck
Subject: Generic 'diff'
In-Reply-To: <4A126C98.6050906@idi.ntnu.no>
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
>