R:浓缩指数

时间:2013-06-14 22:38:44

标签: r

我有一个如下的矢量:

xx <- c(1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1)

我想找到包含索引的索引并将它们组合在一起。在这种情况下,我希望输出在2x2矩阵中看起来像1 6和11 14。我的矢量实际上很长,所以我不能手工完成。谁能帮我这个?感谢。

4 个答案:

答案 0 :(得分:5)

这样的事,也许?

if (xx[1] == 1) {
    rr <- cumsum(c(0, rle(xx)$lengths))
} else {
    rr <- cumsum(rle(xx)$lengths)
}
if (length(rr) %% 2 == 1) {
    rr <- head(rr, -1)
}
oo <- matrix(rr, ncol=2, byrow=TRUE)
oo[, 1] <- oo[, 1] + 1
     [,1] [,2]
[1,]    1    6
[2,]   11   14

此编辑处理以下情况:1)向量以“0”开始而不是“1”和2),其中1的连续出现次数为奇数/偶数。例如:xx <- c(1,1,1,1,1,1,0,0,0,0)

答案 1 :(得分:5)

由于这个问题最初有一个标签'生物信息学',我会提到Bioconductor IRanges (它是基因组上范围的伴侣 {{3 }}

> library(IRanges)
> xx <- c(1,1,1,1,1,1,0,0,0,0,1,1,1,1)
> sl = slice(Rle(xx), 1)
> sl
Views on a 14-length Rle subject

views:
    start end width
[1]     1   6     6 [1 1 1 1 1 1]
[2]    11  14     4 [1 1 1 1]

可以被强制转换为矩阵,但对于下一步而言,这往往不方便

> matrix(c(start(sl), end(sl)), ncol=2)
     [,1] [,2]
[1,]    1    6
[2,]   11   14

其他操作可能会从Rle开始,例如

> xx = c(2,2,2,3,3,3,0,0,0,0,4,4,1,1)
> r = Rle(xx)
> m = cbind(start(r), end(r))[runValue(r) != 0,,drop=FALSE]
> m
     [,1] [,2]
[1,]    1    3
[2,]    4    6
[3,]   11   12
[4,]   13   14

有关?Rle课程的完全灵活性,请参阅帮助页面Rle ;从上面的矩阵转到下面评论中提到的新Rle,可以创建一个适当长度的新Rle,然后使用IRanges作为索引进行子集分配

> r = Rle(0L, max(m))
> r[IRanges(m[,1], m[,2])] = 1L
> r
integer-Rle of length 14 with 3 runs
  Lengths: 6 4 4
  Values : 1 0 1

可以将其扩展为完整的向量

> as(r, "integer")
 [1] 1 1 1 1 1 1 0 0 0 0 1 1 1 1

但通常最好继续对Rle进行分析。该类非常灵活,因此从xx转换为1和0的整数向量的一种方法是

> as(Rle(xx) > 0, "integer")
 [1] 1 1 1 1 1 1 0 0 0 0 1 1 1 1

但是,再次,留在Rle空间通常是有意义的。而GenomicRanges对你的单独问题的回答可能是最好的。

性能(速度)很重要,虽然在这种情况下我认为Rle类提供了很大的灵活性,可以衡量糟糕的性能,最终在矩阵上是一个不太可能的终点进行典型分析。 Nonetheles IRanges基础设施性能

eddi <- function(xx)
    matrix(which(diff(c(0,xx,0)) != 0) - c(0,1),
           ncol = 2, byrow = TRUE)

iranges = function(xx) {
    sl = slice(Rle(xx), 1)
    matrix(c(start(sl), end(sl)), ncol=2)
}

iranges.1 = function(xx) {
    r = Rle(xx)
    cbind(start(r), end(r))[runValue(r) != 0, , drop=FALSE]
}

> xx = sample(c(0, 1), 1e5, TRUE)
> microbenchmark(eddi(xx), iranges(xx), iranges.1(xx), times=10)
Unit: milliseconds
          expr       min        lq    median        uq      max neval
      eddi(xx)  45.88009  46.69360  47.67374 226.15084 234.8138    10
   iranges(xx) 112.09530 114.36889 229.90911 292.84153 294.7348    10
 iranges.1(xx)  31.64954  31.72658  33.26242  35.52092 226.7817    10

答案 2 :(得分:3)

另一个,简短的一个:

cbind(start = which(diff(c(0, xx)) == +1),
      end   = which(diff(c(xx, 0)) == -1))
#      start end
# [1,]     1   6
# [2,]    11  14

我在很长的矢量上进行了测试,它比使用rle略慢。但更可读的恕我直言。如果速度确实是一个问题,你也可以这样做:

xx.diff <- diff(c(0, xx, 0))
cbind(start = which(head(xx.diff, -1) == +1),
      end   = which(tail(xx.diff, -1) == -1))
#      start end
# [1,]     1   6
# [2,]    11  14

答案 3 :(得分:1)

这是另一个以其他人为基础的解决方案。想法,并且更短更快:

matrix(which(diff(c(0,xx,0)) != 0) - c(0,1), ncol = 2, byrow = T)
#     [,1] [,2]
#[1,]    1    6
#[2,]   11   14

我没有测试非基础解决方案,但这里是基础解决方案的比较:

xx = sample(c(0,1), 1e5, T)
microbenchmark(arun(xx), flodel(xx), flodel.fast(xx), eddi(xx))
#Unit: milliseconds
#            expr       min        lq    median        uq       max neval
#        arun(xx) 14.021134 14.181134 14.246415 14.332655 15.220496   100
#      flodel(xx) 12.885134 13.186254 13.248334 13.432974 14.367695   100
# flodel.fast(xx)  9.704010  9.952810 10.063691 10.211371 11.108171   100
#        eddi(xx)  7.029448  7.276008  7.328968  7.439528  8.361609   100