1

私は次のような行列を持っています

      [,1] [,2]
 [1,]    1    3
 [2,]    4    6
 [3,]   11   12
 [4,]   13   14

この行列を次のようなベクトルに変換したい:

# indices 1-6, 11-14 = 1, gap indices 7-10 = 0
xx <- c(1,1,1,1,1,1,0,0,0,0,1,1,1,1)

アイデア: マトリックスには 1 から 14 までの値があります。また、ベクトルの長さも 14 です。最初の列が開始点で、2 番目の列が終了点であると仮定すると、マトリックスに存在する範囲について、つまり、1 ~ 3、4 ~ 6、11 ~ 12、13 ~ 4 (または同等の 1 ~ 6、11 ~ 14)、出力ベクトルでこれらのインデックスの値を 1 にします。また、マトリックスの 7 ~ 10 のギャップは、出力ベクトルのインデックス 7 ~ 10 で値が 0 になるはずです。(編集ありがとうございます)

ただし、行列が行列の最後の値を示さない場合があります。ただし、変換後のサイズは常にわかっています。たとえば、この場合は 20 です。その後、結果のベクトルは次のようになります。

# indices 1-6, 11-14 = 1, gap indices 7-10 = 0, indices 15-20 = 0
xx <- c(1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0)

どうすればループなしでそれを行うことができますか? 私の行列はかなり長いので、ループを使ってみましたが遅いです。

4

3 に答える 3

2

IRangesパッケージを使用した回答は次のとおりです。

require(IRanges)
xx.ir <- IRanges(start = xx[,1], end = xx[,2])
as.vector(coverage(xx.ir))
# [1] 1 1 1 1 1 1 0 0 0 0 1 1 1 1

ベクトル全体の長さの と の値を指定するminと、次のようになります。max

max.val <- 20
min.val <- 1
c(rep(0, min.val-1), as.vector(coverage(xx.ir)), rep(0, max.val-max(xx)))
于 2013-06-15T07:47:43.670 に答える
1

@アルンの答えはより良いようです。

問題を理解したので(または私はそうしますか?)。これは、連続したゼロのシーケンスのみを保持する必要があるという考えを利用したベース R のソリューションです。

find.ones <- function (mat) {
  ones <- rep(0, max(mat))
  ones[c(mat)] <- 1
  ones <- paste0(ones, collapse="")
  ones <- gsub("101", "111", ones)
  ones <- as.numeric(strsplit(ones, "")[[1]])
  ones
}

OPの元の例では:

m <- matrix(c(1, 3, 4, 6, 11, 12, 13, 14), ncol=2, byrow=TRUE)
find.ones(m)
[1] 1 1 1 1 1 1 0 0 0 0 1 1 1 1

ソリューションのベンチマークを行うために、行列を十分大きくしてみましょう。

set.seed(10)
m <- sample.int(n=1e6, size=5e5)                                              
m <- matrix(sort(m), ncol=2, byrow=TRUE)                                           

head(m)                                                           
     [,1] [,2]
[1,]    1    3
[2,]    4    5
[3,]    9   10
[4,]   11   13
[5,]   14   18
[6,]   22   23

system.time(ones <- find.ones(m))

 user  system elapsed 
1.167   0.000   1.167 
于 2013-06-15T07:24:37.737 に答える
1

ここにこれを投げると、ベースRを使用し、必然的なループがによって処理されるため、多少高速になるはずですrep:

zero.lengths <- m[,1] - c(0, head(m[,2], -1)) - 1
one.lengths  <- m[,2] - m[,1] + 1

rep(rep(c(0, 1), nrow(m)),
    as.vector(rbind(zero.lengths, one.lengths)))

または、次を使用した別のソリューションsequence:

out <- integer(m[length(m)])    # or `integer(20)` following OP's edit.
one.starts  <- m[,1]
one.lengths <- m[,2] - m[,1] + 1
one.idx <- sequence(one.lengths) + rep(one.starts, one.lengths) - 1L
out[one.idx] <- 1L
于 2013-06-15T11:49:59.803 に答える