Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use tapply and preserve order of values

Tags:

r

hopefully this is not a too dumb question, but still being an R beginner I have a serious problem with tapply. Lets say

factors <- as.factor( c("a", "b", "c", "a", "b", "c", "a", "b", "c") )
values  <- c( 1, 2, 3, 4, 5, NA, 7, NA, NA )
tapply(
  values,
  factors,
  function(x){
    if( sum(is.na(x)) == 1 ){
      x[ is.na(x) ] <- 0
    }
    return(x)
  }
)

The result is

$a
[1] 1 4 7

$b
[1] 2 5 0

$c
[1]  3 NA NA

However, what I need is to get a vector back which preserves the original order of values, i.e.:

c( 1,2,3,4,5,NA,7,0,NA )

Many thanks in advance.

like image 560
Beasterfield Avatar asked May 23 '11 22:05

Beasterfield


2 Answers

In that case you should use the ave function:

> ave(values, factors, FUN=function(x) {
+     if( sum(is.na(x)) == 1 ){
+       x[ is.na(x) ] <- 0
+     }
+     return(x)
+   }
+ )
[1]  1  2  3  4  5 NA  7  0 NA
like image 85
IRTFM Avatar answered Sep 22 '22 22:09

IRTFM


A simple for loop does this very simply:

fun <- function(x){
   if(sum(is.na(x)) == 1){x[is.na(x)] <- 0}
       return(x)
}

for (i in unique(factors)){
   values[i == factors] <- fun(values[i == factors])
}
like image 38
joran Avatar answered Sep 23 '22 22:09

joran