[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