Robert Long
Robert Long

Reputation: 6802

Combining two vectors element-by-element

I have 2 vectors, such as these:

A <- c(1,2,NA,NA,NA,NA,7)
B <- c(NA,NA,3,4,NA,NA,7)

I would like to combine them so that the resulting vector is

1,2,3,4,NA,NA,-1

That is

  1. when only 1 value (say X) in either vector at position i exists (the other being NA) the new vector should take the value X at position i.

  2. when both values are NA at position i, the new vector should take the value NA at position i

  3. when both vectors have a value at position i, the new vector should take the value -1 at position i.

I can easily do this with a loop, but it is very slow on a large dataset so can anyone provide a fast way to do this ?

Upvotes: 8

Views: 3366

Answers (3)

thelatemail
thelatemail

Reputation: 93813

A bit late to the party, but here is another option defining a function that works by applying rules to the two vectors cbind-ed together.

# get the data
A <- c(1,2,NA,NA,NA,NA,7)
B <- c(NA,NA,3,4,NA,NA,7)

# define the function
process <- function(A,B) {
  x <- cbind(A,B)
  apply(x,1,function(x) {
    if(sum(is.na(x))==1) {na.omit(x)} else
    if(all(is.na(x))) {NA} else
    if(!any(is.na(x))) {-1}
  })
}

# call the function
process(A,B)
#[1]  1  2  3  4 NA NA -1

The main benefit of using a function is that it is easier to update the rules or the inputs to apply the code to new data.

Upvotes: 2

Roland
Roland

Reputation: 132626

A <- c(1,2,NA,NA,NA,NA,7)
B <- c(NA,NA,3,4,NA,NA,7)
C <- rowMeans(cbind(A,B),na.rm=TRUE)
C[which(!is.na(A*B))]<- -1
#[1]   1   2   3   4 NaN NaN  -1

Benchmarks:

Unit: microseconds
          expr    min     lq median     uq     max
1 Roland(A, B) 17.863 19.095 19.710 20.019  68.985
2   Sven(A, B) 11.703 13.243 14.167 14.783 100.398

Upvotes: 5

Sven Hohenstein
Sven Hohenstein

Reputation: 81683

These commands create the vector:

X <- A
X[is.na(A)] <- B[is.na(A)]
X[is.na(B)] <- A[is.na(B)]
X[!is.na(A & B)] <- -1

#[1]  1  2  3  4 NA NA -1

Upvotes: 11

Related Questions