Given two values x and b, I want a function to clamp x to fall within [-b, b]. In particular:
- If
xis less than or equal to-b, then the function returns-b; - If
xis greater than-band less thanb, then the function returnsx; - If
xis greater than or equal tob, then the function returnsb.
In R I wrote the following function truncfn. Only part of this function works. Where did I make mistake? Is there an easier way to do this?
b <- 5 truncfn <- function(x){ if((x<(-b))||(x==-b)) -b if((x>(-b))&&(x<b)) x if((x>b)||(x==b)) b } truncfn(10) 5 truncfn(4) truncfn(-10) 2 Answers
I would use the pmin and pmax functions to do this is a single expression without if statements:
b <- 5 x <- seq(-10, 10) pmax(pmin(x, b), -b) # [1] -5 -5 -5 -5 -5 -5 -4 -3 -2 -1 0 1 2 3 4 5 5 5 5 5 5 You could have fixed your function by replacing the second and third if statements with else if statements (or alternately using return(b), return(x) and return(-b)). Here is a working version (I've taken the liberty to use <= instead of separately checking with < and ==):
truncfn <- function(x){ if (x <= -b) -b else if (x > -b && x < b) x else b } truncfn(10) # [1] 5 truncfn(4) # [1] 4 truncfn(-10) # [1] -5 However note that the function I wrote with pmin and pmax can take a whole vector as input, while yours is limited to taking a single number.
You can use raster::clamp
library(raster) b <- 5 v <- -10:10 raster::clamp(v, -b, b) # [1] -5 -5 -5 -5 -5 -5 -4 -3 -2 -1 0 1 2 3 4 5 5 5 5 5 5