3

私はRコードで"%within[]%" <- function(x,y){x>=y[1] & x<=y[2]}(意味xはコンパクトセットにありますy)をよく使用しますが、それは非常に遅いと確信しています。もっと速いものはありますか?>が定義されているすべての場所で機能する必要があります。

編集:ベクトルと昇順の2要素ベクトルにxなる可能性があります...y

EDIT2:(私の知る限り)誰も(私の知る限り)のようなrOperatorクイックC演算子を実装するパッケージを書いていないのは奇妙です%w/i[]%, %w/i[[%, ...

EDIT3: 仮定を行うと結果が変更されるため、質問が一般的すぎることに気付きましたx,y。ご意見をお寄せいただきありがとうございます。

4

4 に答える 4

6
"%within[]%" <- function(x,y){x>=y[1] & x<=y[2]}

x <- 1:10
y <- c(3,5)

x %within[]% y
"%within[]2%" <- function(x,y) findInterval(x,y,rightmost.closed=TRUE)==1
x %within[]2% y

library(microbenchmark)

microbenchmark(x %within[]% y,x %within[]2% y)

Unit: microseconds
             expr   min    lq median    uq    max
1  x %within[]% y 1.849 2.465 2.6185 2.773 11.395
2 x %within[]2% y 4.928 5.544 5.8520 6.160 37.265

x <- 1:1e6
microbenchmark(x %within[]% y,x %within[]2% y)

Unit: milliseconds
             expr      min       lq   median       uq      max
1  x %within[]% y 27.81535 29.60647 31.25193 56.68517 88.16961
2 x %within[]2% y 20.75496 23.07100 24.37369 43.15691 69.62122

これはおそらく Rcpp の仕事です。

于 2013-02-21T13:09:44.597 に答える
3

単純な Rcpp 実装でパフォーマンスを少し改善できます。

library(Rcpp)
library(microbenchmark)

withinR <- function(x,y) x >= y[1] & x <= y[2]
cppFunction("LogicalVector withinCpp(const NumericVector& x, const NumericVector& y) {
  double min = y[0], max = y[1];

  int n = x.size();
  LogicalVector out(n);

  for(int i = 0; i < n; ++i) {
    double val = x[i];
    if (NumericVector::is_na(val)) {
      out[i] = NA_LOGICAL;
    } else {
      out[i] = val >= min & val <= max;
    }

  }
  return out;
}")

x <- sample(100, 1e5, rep = T)

stopifnot(all.equal(withinR(x, c(25, 50)), withinCpp(x, c(25, 50))))

microbenchmark(
  withinR(x, c(25, 50)),
  withinCpp(x, c(25, 50))
)

C++ バージョンは、私のコンピューターでは約 4 倍高速です。より多くの Rcpp トリックを使用したい場合は、おそらくさらに微調整できますが、これはすでにかなり高速に思えます。R バージョンでさえ、ボトルネックになる前に非常に頻繁に呼び出す必要があります。

# Unit: microseconds
#                      expr  min   lq median   uq  max
# 1 withinCpp(x, c(25, 50))  635  659    678 1012 27385
# 2   withinR(x, c(25, 50)) 1969 2031   2573 2954 4082
于 2013-02-21T14:50:26.073 に答える
1

まあ、これが遅いと考えられるかどうかはわかりませんが、ここにちょっとしたベンチマークがあります:

R> within <- function(x,y){return(x>=y[1] & x<=y[2])}
R> microbenchmark(within(2,c(1,5)))
Unit: microseconds
               expr   min     lq median    uq    max neval
 within(2, c(1, 5)) 2.667 2.8305 2.9045 2.969 15.818   100

R> within2 <- function(x,y) x>=y[1] & x<=y[2]
R> microbenchmark(within2(2,c(1,5)))
Unit: microseconds
                expr   min     lq median    uq    max neval
 within2(2, c(1, 5)) 2.266 2.3205  2.398 2.483 12.472   100

R> microbenchmark(2>=1 & 2<=5)
Unit: nanoseconds
            expr min    lq median  uq  max neval
 2 >= 1 & 2 <= 5 781 821.5    850 911 5701   100

したがって、Konrad Rudolph によって提案されているように、を省略するreturnと、処理が少し速くなるようです。しかし、関数を書かない方がはるかに高速です。

于 2013-02-21T13:02:25.523 に答える
1

ツリーベースの構造xは、多くの値が含まれている場合にパフォーマンスが向上します。要件を数値に限定できる場合、2 つのオプションがあります。

整数の間隔ツリーの実装は、Bioconductor パッケージIRangesにあります。

デフォルトでは、RSQLite は埋め込み SQLite ライブラリをrtreeを有効にしてコンパイルします。これは、任意の数値で使用できます。

于 2013-02-21T13:06:33.280 に答える