11

Rでは、範囲から整数を抽出する効率的な方法は何ですか?

範囲のマトリックスがあるとしましょう(column1 = start、column2 = end)

1   5
3   6
10  13

マトリックス内のすべての範囲の包括的な一意の整数をオブジェクトに格納したいと思います。

1
2
3
4
5
6
10
11
12
13

これは、〜400万の範囲を含むマトリックスに適用されるため、誰かがある程度効率的なソリューションを提供できることを願っています.

4

4 に答える 4

12

start = 3、end = 7 で、それぞれを 1 から始まる数直線上で「1」としてマークしたとします。

starts:     0 0 1 0 0 0 0 0 0 ...
ends + 1:   0 0 0 0 0 0 0 1 0 ...

始点の累積和から終点の累積和を引いたものと、その差は次のとおりです。

cumsum(starts):   0 0 1 1 1 1 1 1 1 ...
cumsum(ends + 1): 0 0 0 0 0 0 0 1 1 ...
diff:             0 0 1 1 1 1 1 0 0

差分の 1 の位置は次のとおりです。

which(diff > 0): 3 4 5 6 7

tabulate を使用して、同じ場所で複数の開始/終了を許可します。

range2 <- function(ranges)
{
    max <- max(ranges)
    starts <- tabulate(ranges[,1], max)
    ends <- tabulate(ranges[,2] + 1L, max)
    which(cumsum(starts) - cumsum(ends) > 0L)
}

質問に対して、これは

> eg <- matrix(c(1, 3, 10, 5, 6, 13), 3)
> range2(eg)
 [1]  1  2  3  4  5  6 10 11 12 13

Andrieの例では、かなり高速です

 > system.time(runs <- range2(xx))
   user  system elapsed 
  0.108   0.000   0.111 

(これは、GenomicRangesがあなたの友人になるかもしれないDNA シーケンス分析に少し似ているように聞こえます。読み取りにはcoverageおよびslice関数を使用し、おそらく で入力しますreadGappedAlignments)。

于 2012-08-12T04:47:25.157 に答える
5

とを使用sequencerepます。

x <- matrix(c(1, 5, 3, 6, 10, 13), ncol=2, byrow=TRUE)

ranges <- function(x){
  len <- x[, 2] - x[, 1] + 1
  #allocate space
  a <- b <- vector("numeric", sum(len))
  a <- rep(x[, 1], len) 
  b <- sequence(len)-1
  unique(a+b)
}

ranges(x)
[1]  1  2  3  4  5  6 10 11 12 13

これはベクトル化されたコードのみを使用するため、大規模なデータ セットであっても非常に高速です。私のマシンでは、100 万行の入力行列を実行するのに約 5 秒かかります。

set.seed(1)
xx <- sample(1e6, 1e6)
xx <- matrix(c(xx, xx+sample(1:100, 1e6, replace=TRUE)), ncol=2)
str(xx)
 int [1:1000000, 1:2] 265509 372124 572853 908206 201682 898386 944670 660794 629110 61786 ...

system.time(zz <- ranges(xx))
user  system elapsed 
   4.33    0.78    5.22 

str(zz)
num [1:51470518] 265509 265510 265511 265512 265513 ...
于 2012-08-12T00:53:37.413 に答える
5

特に効率的かどうかはわかりませんが、範囲のマトリックスが次のranges場合は次のようになります。

unique(unlist(apply(ranges, 1, function(x) x[1]:x[2])))
于 2012-08-12T00:38:23.690 に答える
3

次のような単純なものではありませんか?

x <- matrix(c(1, 5, 3, 6, 10, 13), ncol=2, byrow=TRUE)
do.call(":",as.list(range(x)))
[1]  1  2  3  4  5  6  7  8  9 10 11 12 13

編集

スティックの端が間違っているように見えますが、私の答えは を使用するように変更できますがunion、これは のラッパーにすぎませんunique:

Reduce("union",apply(x,1,function(y) do.call(":",as.list(y))))
[1]  1  2  3  4  5  6 10 11 12 13
于 2012-08-12T10:04:54.013 に答える