R’s ave() function is way more useful than its name suggests – it’s basically a version of tapply() that lets you return a vector the same length as the input, and slots those values back into the same order as the input for you.
> x <- 1:10
> ave(x, x %% 2, FUN=function(d) d-mean(d))
[1] -4 -4 -2 -2 0 0 2 2 4 4
You can achieve a similar effect with ddply(), but it requires a couple extra copies of the data, as well as a couple auxiliary variables:
> x <- 1:10
> val <- ddply(data.frame(x=x, id=1:10), .(x %% 2),
function(d) {d$y <- d$x-mean(d$x); d})
> val[order(val$id),]$y
[1] -4 -4 -2 -2 0 0 2 2 4 4
Is there some other plyr technique that matches the lightweight approach I can get with ave()?
You can shorten the
ddplycode somewhat by usingtransform:but I don’t think that
ddplyand other plyr functions are really meant to replicate the functionality ofavethat you describe. For splitting and recombining single atomic vectors,tapply(andave) are probably the right tools for the job.