Using the Rcpp sugar function clamp

January 7, 2013
By

(This article was first published on Rcpp Gallery, and kindly contributed to R-bloggers)

Since the 0.10.* release series, Rcpp contains a new sugar function `clamp` which can be used to limit vectors to both a minimum and maximim value. This recent StackOverflow question permitted `clamp` to shine. We retake some of the answers, including the `clamp` entry by Romain.

We first define the three R versions.

``````pminpmaxClamp <- function(x, a, b) {
pmax(a, pmin(x, b) )
}

ifelseClamp <- function(x, a, b) {
ifelse(x <= a,  a, ifelse(x >= b, b, x))
}

operationsClamp <- function(x, a, b) {
a + (x-a > 0)*(x-a) - (x-b > 0)*(x-b)
}
``````

We then define some data, and ensure that these versions all producing identical results.

``````set.seed(42)
x <- rnorm(100000)

a <- -1.0
b <- 1.0
stopifnot(all.equal(pminpmaxClamp(x,a,b), ifelseClamp(x,a,b), operationsClamp(x,a,b)))
``````

Next is the C++ solution: a one-liner thanks to the existing sugar function.

``````#include

using namespace Rcpp;

// [[Rcpp::export]]
NumericVector rcppClamp(NumericVector x, double mi, double ma) {
return clamp(mi, x, ma);
}
``````

We can then check and benchmark the new C++ version.

``````stopifnot(all.equal(pminpmaxClamp(x,a,b), rcppClamp(x,a,b)))

library(rbenchmark)
benchmark(pminpmaxClamp(x, a, b),
ifelseClamp(x, a, b),
operationsClamp(x, a, b),
rcppClamp(x, a, b),
order="relative")[,1:4]
``````
```                      test replications elapsed relative
4       rcppClamp(x, a, b)          100   0.119    1.000
3 operationsClamp(x, a, b)          100   0.505    4.244
1   pminpmaxClamp(x, a, b)          100   0.530    4.454
2     ifelseClamp(x, a, b)          100   5.268   44.269
```

We see a decent gain of the Rcpp version even relative to these vectorised R solutions. Among these, the simplest (based on `ifelse`) is by far the slowest. The parallel min/max version is about as faster as the clever-but-less-readable expression-based solution.

Real “production” solutions will of course need some more testing of inputs etc. However, as an illustration of `clamp` this example has hopefully been compelling.

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...