首页 > 解决方案 > “截断”数字在R中快速位于一个范围内

问题描述

是否有任何简单的内置 R 函数或快速破解来将给定的数字设置在给定的范围内(如果它还没有的话)?我想要这样做的东西:

truncate <- function(x,a,b) min(max(x,a),b)

这当然很简单,但似乎应该内置。我知道截断在 R 中具有不同的含义(截断小数),但它在概率和统计中具有我的含义。

标签: rbuilt-in

解决方案


一些(矢量化)选项,包括microbenchmark

set.seed(2019)
x <- sample(1:1000, 10^6, replace = T)

# Option 1: Using replace
truncate1 <- function(x, a, b) {
    replace(replace(x, x < a, a), x > b, b)
}

# Option 2: Direct indexing
truncate2 <- function(x, a, b) {
    x[x < a] <- a
    x[x > b] <- b
    x
}

# Option 3: Using vectorised min/max
truncate3 <- function(x, a, b) pmin(pmax(x, a), b)

# Option 4: Rcpp version
library(Rcpp)
cppFunction("
    NumericVector truncate4(NumericVector x, double a, double b) {
        x[x < a] = a;
        x[x > b] = b;
        return(x);
    }
    ")

library(microbenchmark)
res <- microbenchmark(
    truncate1 = truncate1(x, 20, 50),
    truncate2 = truncate2(x, 20, 50),
    truncate3 = truncate3(x, 20, 50),
    truncate4 = truncate4(x, 20, 50))
#Unit: milliseconds
#      expr      min       lq     mean   median       uq      max neval
# truncate1 21.11311 24.72446 28.53179 26.93042 30.36175 67.24833   100
# truncate2 18.92472 23.04515 28.72290 26.33326 29.27687 76.96418   100
# truncate3 15.25429 17.89847 23.96331 21.31570 24.56693 63.58878   100
# truncate4 24.37332 27.33767 32.30241 29.97932 33.41832 72.65265   100

推荐阅读