如何找到连续n个连续零的索引

时间:2018-05-13 00:22:15

标签: r vector sequence difference

假设我有这些数据:

  x = c(14,14, 6,  7 ,14 , 0 ,0  ,0 , 0,  0,  0 , 0 , 0,  0 , 0 , 0 , 0,  9  ,1 , 3  ,8  ,9 ,15,  9 , 8, 13,  8,  4 , 6 , 7 ,10 ,13,  3,
 0 , 0 , 0 , 0 , 0 , 0,  0,  0 , 0 , 0 , 0,  0,  0,  0,  0  ,0,  0 , 0 , 0,  0,  0,  0,  0 , 0,  0, 4 , 7  ,4,  5 ,16 , 5  ,5 , 9 , 4  ,4,  9 , 8,  2,  0  ,0  ,0  ,0  ,0,  0,  0,  0  ,0 , 0,  0,  0,  0,  0,  0,  0,  0,0)

x
 [1] 14 14  6  7 14  0  0  0  0  0  0  0  0  0  0  0  0  9  1  3  8  9 15  9  8
[26] 13  8  4  6  7 10 13  3  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
[51]  0  0  0  0  0  0  0  0  4  7  4  5 16  5  5  9  4  4  9  8  2  0  0  0  0
[76]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  

我希望恢复从一行中有超过3个零并且在非零之前以最后0结束的索引。

例如,

我会得到

6,17为第一批零点等等。

3 个答案:

答案 0 :(得分:12)

以下是两种基本R方法:

1)rle 首先运行rle然后计算ok以选出长度超过3的零序列。然后,我们计算所有重复序列的startsends,并在最后对ok子序列进行子集化。

with(rle(x), {
  ok <- values == 0 & lengths > 3
  ends <- cumsum(lengths)
  starts <- ends - lengths + 1
  data.frame(starts, ends)[ok, ]
})

,并提供:

  starts ends
1      6   17
2     34   58
3     72   89

2)gregexpr 取每个数字的符号 - 将为0或1,然后将它们连接成一个长字符串。然后使用gregexpr查找至少4个零的位置。结果给出了开始和结束可以从加上match.length属性减去1开始计算。

s <- paste(sign(x), collapse = "")
g <- gregexpr("0{4,}", s)[[1]]
data.frame(starts = 0, ends = attr(g, "match.length") - 1) + g

,并提供:

  starts ends
1      6   17
2     34   58
3     72   89

答案 1 :(得分:7)

Starts = which(diff(x == 0) == 1) + 1
Ends   = which(diff(x == 0) == -1)
if(length(Ends) < length(Starts)) {
    Ends = c(Ends, length(x)) }

Starts
[1]  6 34 72
Ends
[1] 17 58 89

这适用于您的测试数据,但允许任何零序列,包括短序列。为了确保您获得长度至少为n的序列,请添加:

n=3
Long = which((Ends - Starts) >= n)
Starts = Starts[Long]
Ends = Ends[Long]

答案 2 :(得分:5)

如果x恰好是data.table的一列,则可以

library(data.table)
dt <- data.table(x = x)

dt[, if(.N > 3 & all(x == 0)) .(starts = first(.I), ends = last(.I))
   , by = rleid(x)]

#    rleid starts ends
# 1:     5      6   17
# 2:    22     34   58
# 3:    34     72   89

说明:

  • rleid(x)x中的每个元素指定一个ID(整数) “运行”元素是其成员,其中“运行”表示序列 相邻的相等值。
  • 根据{{​​1}}
  • dt[, <code>, by = rle(x)]分区dt,并为rleid(x)行的每个子集计算<code>。结果堆叠在一起dt
  • data.table是给定子集中的元素数量
  • .N是与子集
  • 对应的行号的向量
  • .Ifirst给出了向量的第一个和最后一个元素
  • last.(<stuff>)

    相同

    括号内的list(<stuff>)函数,rleid分组,.N和.I符号,byfirst函数是last包的一部分