20

Rの素晴らしい関数は、そのドキュメントに示されているように、引数でfindInterval()左閉じサブ間隔を使用します。vec

もしi <- findInterval(x,v)、私たちは持っていますv[i[j]] <= x[j] < v[i[j] + 1]

右閉じのサブインターバルが必要な場合、どのようなオプションがありますか? 私が思いついた最高のものはこれです:

findInterval.rightClosed <- function(x, vec, ...) {
  fi <- findInterval(x, vec, ...)
  fi - (x==vec[fi])
}

別のものも機能します:

findInterval.rightClosed2 <- function(x, vec, ...) {
  length(vec) - findInterval(-x, -rev(vec), ...)
}

ここに小さなテストがあります:

x <- c(3, 6, 7, 7, 29, 37, 52)
vec <- c(2, 5, 6, 35)
findInterval(x, vec)
# [1] 1 3 3 3 3 4 4
findInterval.rightClosed(x, vec)
# [1] 1 2 3 3 3 4 4
findInterval.rightClosed2(x, vec)
# [1] 1 2 3 3 3 4 4

しかし、より良い解決策があれば、他の解決策を見たいと思います。「より良い」とは、「なんとなく満足度が高い」、「面倒に感じない」、あるいは「より効率的」という意味です。=)

( にはrightmost.closed引数がありますがfindInterval()、それは異なります。最終的なサブ間隔のみを参照し、異なる意味を持つことに注意してください。)

4

3 に答える 3

10

編集:すべての通路の大掃除。

あなたは見るかもしれませんcut。デフォルトでcutは、左が開いて右が閉じた間隔になりますが、これは適切な引数 ( right) を使用して変更できます。あなたの例を使用するには:

x <- c(3, 6, 7, 7, 29, 37, 52)
vec <- c(2, 5, 6, 35)
cutVec <- c(vec, max(x)) # for cut, range of vec should cover all of x

次に、同じことを行う 4 つの関数を作成します。OP から 2 つ、Josh O'Brien から 1 つ、そしてcut. cutデフォルト設定から変更された2 つの引数:include.lowest = TRUE最小 (左端) の間隔の両側で閉じた間隔を作成します。因子を作成するのではなく、単にビンの整数値を返すようにしますlabels = FALSEcut

findInterval.rightClosed <- function(x, vec, ...) {
  fi <- findInterval(x, vec, ...)
  fi - (x==vec[fi])
}
findInterval.rightClosed2 <- function(x, vec, ...) {
  length(vec) - findInterval(-x, -rev(vec), ...)
}
cutFun <- function(x, vec){
    cut(x, vec, include.lowest = TRUE, labels = FALSE)
}
# The body of fiFun is a contribution by Josh O'Brien that got fed to the ether.
fiFun <- function(x, vec){
    xxFI <- findInterval(x, vec * (1 + .Machine$double.eps))
}

すべての関数は同じ結果を返しますか? うん。( cutVecforの使用に注意してくださいcutFun)

mapply(identical, list(findInterval.rightClosed(x, vec)),
  list(findInterval.rightClosed2(x, vec), cutFun(x, cutVec), fiFun(x, vec)))
# [1] TRUE TRUE TRUE

より要求の厳しいビンへのベクトル:

x <- rpois(2e6, 10)
vec <- c(-Inf, quantile(x, seq(.2, 1, .2)))

同一かどうかをテストします ( の使用に注意してくださいunname)

mapply(identical, list(unname(findInterval.rightClosed(x, vec))),
  list(findInterval.rightClosed2(x, vec), cutFun(x, vec), fiFun(x, vec)))
# [1] TRUE TRUE TRUE

そしてベンチマーク:

library(microbenchmark)
microbenchmark(findInterval.rightClosed(x, vec), findInterval.rightClosed2(x, vec),
  cutFun(x, vec), fiFun(x, vec), times = 50)
# Unit: milliseconds
#                                expr       min        lq    median        uq       max
# 1                    cutFun(x, vec)  35.46261  35.63435  35.81233  36.68036  53.52078
# 2                     fiFun(x, vec)  51.30158  51.69391  52.24277  53.69253  67.09433
# 3  findInterval.rightClosed(x, vec) 124.57110 133.99315 142.06567 155.68592 176.43291
# 4 findInterval.rightClosed2(x, vec)  79.81685  82.01025  86.20182  95.65368 108.51624

今回の走行からcut、最速のようです。

于 2012-11-20T22:03:31.600 に答える