How to use tapply and keep order of values

I hope this is not a too stupid question, but still being a R newbie, I have a serious problem. Let's 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) } ) 

Result

 $a [1] 1 4 7 $b [1] 2 5 0 $c [1] 3 NA NA 

However, I need to get back a vector that preserves the original order of values, i.e.

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

Thank you very much in advance.

+6
source share
3 answers

In this 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 
+7
source

A simple for loop makes this very easy:

 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]) } 
+1
source

The option is to use the replacement method for split ():

 ## create a copy to store the result after replacement res <- values ## use split replacement method to split, apply, and recombine split(res, factors) <- lapply(split(res, factors), function(x){ if( sum(is.na(x)) == 1 ){ x[ is.na(x) ] <- 0 } return(x) } ) 
0
source

Source: https://habr.com/ru/post/888861/


All Articles