r - Assign values by group when all that matters is the number of group members -


i recently ran following grouped operation: each group, values assigned evenly distributed numbers between -0.5 , 0.5, , if group has 1 element assigned value 0. instance, if had following observed groups:

g <- c("a", "a", "b", "b", "a", "c") 

then expect assigned values:

outcome <- c(-0.5, 0, -0.5, 0.5, 0.5, 0) 

the 3 observations in group assigned values -0.5, 0, , 0.5 (in order), 2 observations in group b assigned values -0.5 , 0.5 (in order), , 1 observation in group c assigned value 0.

normally when perform grouped operation on 1 vector vector, use ave function, form ave(data.vector, group.vector, fun=function.to.apply.to.each.groups.data.vector.subset). in operation need know number of members in group, there no data.vector. result, ended making data vector ignored in call ave:

ave(rep(na, length(g)), g, fun=function(x) {   if (length(x) == 1) {     return(0)   } else {     return(seq(-0.5, 0.5, length=length(x)))   } }) # [1] -0.5  0.0 -0.5  0.5  0.5  0.0 

while gives me correct answer, it's pretty unsatisfying need make data vector ignore. there better way assign values group when matters number of elements in group?

from comments doesn't seem there's version of ave takes group , function called number of elements in each group. suppose not particularly surprising since it's pretty specialized operation.

if had roll own version of ave desired properties thin wrapper around ave:

ave.len <- function(..., fun) {   l <- list(...)   do.call("ave", c(list(x=rep(na, length(l[[1]]))), l, fun=function(x) fun(length(x)))) }  # original operation, using @akrun's 1-line command sequences g <- c("a", "a", "b", "b", "a", "c") ave.len(g, fun=function(n) seq(-0.5, 0.5, length=n)* (n!=1)+0l) # [1] -0.5  0.0 -0.5  0.5  0.5  0.0  # group of size n has n^th letter in alphabet ave.len(g, fun=function(n) rep(letters[n], n)) # [1] "c" "c" "b" "b" "c" "a"  # multiple groups via ... argument (here everything's in own group) ave.len(g, 1:6, fun=function(n) rep(letters[n], n)) # [1] "a" "a" "a" "a" "a" "a" 

Comments

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -