To preserve NA if both parameters are NA (reset @Ben Bolker approach using cbind ):
apply(cbind(x1, x2), 1, function(x) ifelse(all(is.na(x)), NA, sum(x, na.rm=T)))
Or, if you prefer to use the rowSums function (which is attractive because it is vectorized, whereas the apply and mapply solutions are not):
rowSums(cbind(x1, x2), na.rm=T) + ifelse(is.na(x1) & is.na(x2), NA, 0)
None of them will be as fast as the Rcpp function (which would only have to scroll through two inputs once):
library(Rcpp) sum.na.ign <- cppFunction(" NumericVector sumNaIgn(NumericVector x, NumericVector y) { const int n = x.size(); NumericVector out(n); for (int i=0; i < n; ++i) { if (R_IsNA(x[i])) { out[i] = y[i]; } else if (R_IsNA(y[i])) { out[i] = x[i]; } else { out[i] = x[i] + y[i]; } } return out; }") sum.na.ign(x1, x2)
We can compare (along with a solution based on mapply from @J. Won.) For large vectors:
# First two functions along with mapply-based solution from @J. Won. f1 <- function(x1, x2) apply(cbind(x1, x2), 1, function(x) ifelse(all(is.na(x)), NA, sum(x, na.rm=T))) f2 <- function(x1, x2) rowSums(cbind(x1, x2), na.rm=T) + ifelse(is.na(x1) & is.na(x2), NA, 0) NAsum <- function(...) { if(any(!is.na(c(...)))) return(sum(..., na.rm=TRUE)) return(NA) } jwon <- function(x1, x2) mapply(NAsum, x1, x2) set.seed(144) x1 <- sample(c(NA, 1:10), 10000, replace=T) x2 <- sample(c(NA, 1:10), 10000, replace=T) all.equal(jwon(x1, x2), f1(x1, x2), f2(x1, x2), sum.na.ign(x1, x2))
The rowSums solution rowSums vectorized and therefore faster than the apply and mapply (they will be slow with 1 million vectors), but the custom Rcpp solution is more than 10 times faster than the rowSums approach. Your vectors should probably be quite large for Rcpp to be useful compared to rowSums .