Clip values between a minimum and maximum allowed value in R

前端 未结 4 1840
不思量自难忘°
不思量自难忘° 2020-12-13 20:34

In Mathematica there is the command Clip[x, {min, max}] which gives x for min<=x<=max, min for x

相关标签:
4条回答
  • 2020-12-13 20:46

    Rcpp has clamp for this:

    cppFunction('NumericVector rcpp_clip( NumericVector x, double a, double b){
        return clamp( a, x, b ) ;
    }')
    

    Here is a quick benchmark showing how it performs against other methods discussed :

    pmin_pmax_clip <- function(x, a, b) pmax(a, pmin(x, b) )
    ifelse_clip <- function(x, a, b) {
      ifelse(x <= a,  a, ifelse(x >= b, b, x))
    }
    operations_clip <- function(x, a, b) {
      a + (x-a > 0)*(x-a) - (x-b > 0)*(x-b)
    }
    x <- rnorm( 10000 )
    require(microbenchmark)
    
    microbenchmark( 
      pmin_pmax_clip( x, -2, 2 ), 
      rcpp_clip( x, -2, 2 ), 
      ifelse_clip( x, -2, 2 ), 
      operations_clip( x, -2, 2 )
    )
    # Unit: microseconds
    #                        expr      min        lq   median        uq       max
    # 1     ifelse_clip(x, -2, 2) 2809.211 3812.7350 3911.461 4481.0790 43244.543
    # 2 operations_clip(x, -2, 2)  228.282  248.2500  266.605 1120.8855 40703.937
    # 3  pmin_pmax_clip(x, -2, 2)  260.630  284.0985  308.426  336.9280  1353.721
    # 4       rcpp_clip(x, -2, 2)   65.413   70.7120   84.568   92.2875  1097.039    
    
    0 讨论(0)
  • 2020-12-13 20:56

    Here's a method with nested pmin and pmax setting the bounds:

     fenced.var <- pmax( LB, pmin( var, UB))
    

    It will be difficult to find a method that is faster. Wrapped in a function that defaults to a range of 3 and 7:

    fence <- function(vec, UB=7, LB=3) pmax( LB, pmin( vec, UB))
    
    > fence(1:10)
     [1] 3 3 3 4 5 6 7 7 7 7
    
    0 讨论(0)
  • 2020-12-13 21:04

    I believe that would be clamp() from the raster package.

    library(raster)
    clamp(x, lower=-Inf, upper=Inf, ...)
    
    0 讨论(0)
  • 2020-12-13 21:05

    Here's one function that will work for both vectors and matrices.

    myClip <- function(x, a, b) {
        ifelse(x <= a,  a, ifelse(x >= b, b, x))
    }
    
    myClip(x = 0:10, a = 3,b = 7)
    #  [1] 3 3 3 3 4 5 6 7 7 7 7
    
    myClip(x = matrix(1:12/10, ncol=4), a=.2, b=0.7)
    # myClip(x = matrix(1:12/10, ncol=4), a=.2, b=0.7)
    #      [,1] [,2] [,3] [,4]
    # [1,]  0.2  0.4  0.7  0.7
    # [2,]  0.2  0.5  0.7  0.7
    # [3,]  0.3  0.6  0.7  0.7
    

    And here's another:

    myClip2 <- function(x, a, b) {
        a + (x-a > 0)*(x-a) - (x-b > 0)*(x-b)
    }
    
    myClip2(-10:10, 0, 4)
    # [1] 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 4 4 4 4 4 4
    
    0 讨论(0)
提交回复
热议问题