# Comparing ifelse with C++ for loop with ifs

June 19, 2014
By

(This article was first published on ECONinfo » Rblogger, and kindly contributed to R-bloggers)

I currently am reading a bit about using Rcpp and its potential for speeding up R. I found one unexpected example in the lecture from Hadley Wickham:

``````require(Rcpp)
signR <- function(x) {
if (x > 0) {
1
} else if (x == 0) {
0
} else {
-1
}
}

cppFunction('int signC(int x) {
if (x > 0) {
return 1;
} else if (x == 0) {
return 0;
} else {
return -1;
}
}')

require(microbenchmark)
microbenchmark(signC(rnorm(1)), signR(rnorm(1)),times = 1e5)
``````
```## Unit: microseconds
##             expr   min    lq median   uq  max neval
##  signC(rnorm(1)) 2.832 3.186  3.540 3.54 4130 1e+05
##  signR(rnorm(1)) 2.478 3.186  3.186 3.54 2641 1e+05```

As expected, the two versions perform nearly identical. Now for the surprise: I changed the scalar version of signC into a vectorized version:

``````library(Rcpp)

cppFunction('IntegerVector signCVec(NumericVector x){
int n = x.size();
IntegerVector out(n);
for(int i = 0; i < n; i++){
if(x[i] > 0 ){
out[i] = 1;
} else if(x[i] == 0){
out[i] = 0;
} else {
out[i] = -1;
}
}
return out;
}

')

signRVec <- function(x) {
ifelse(x > 0,1, ifelse(x == 0,0,-1))
}
``````

Now I would have expected the two functions also to be rather similar in execution, but see for yourself:

``````x = rnorm(1e6)

microbenchmark(signCVec(x), signRVec(x),times = 10)
``````
```## Unit: milliseconds
##         expr    min      lq  median      uq     max neval
##  signCVec(x)   8.07   8.103   8.311   8.761   8.952    10
##  signRVec(x) 571.91 581.988 607.664 620.322 743.546    10```

Wow: A 60-odd-times reduction using Rcpp.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...