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

wol*_*oor 10 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  
Run Code Online (Sandbox Code Playgroud)

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

例如,

我会的

6,17为第一个零点,等等.

G. *_*eck 12

以下是两种基本R方法:

1)首先运行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, ]
})
Run Code Online (Sandbox Code Playgroud)

赠送:

  starts ends
1      6   17
2     34   58
3     72   89
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

赠送:

  starts ends
1      6   17
2     34   58
3     72   89
Run Code Online (Sandbox Code Playgroud)


G5W*_*G5W 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
Run Code Online (Sandbox Code Playgroud)

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

n=3
Long = which((Ends - Starts) >= n)
Starts = Starts[Long]
Ends = Ends[Long]
Run Code Online (Sandbox Code Playgroud)


WeN*_*Ben 5

通过使用dplyr,得到diff当时如果diff不等于0,它们不属于同一组,在cumsum我们得到灌注之后

library(dplyr)
df=data.frame('x'=x,rownumber=seq(length(x)))
df$Groupid=cumsum(c(0,diff(df$x==0))!=0)
df%>%group_by(Groupid)%>%summarize(start=first(rownumber),end=last(rownumber),number=first(x),size=n())%>%filter(number==0&size>=3)
# A tibble: 3 x 5
  Groupid start   end number  size
    <int> <int> <int>  <dbl> <int>
1       1     6    17      0    12
2       3    34    58      0    25
3       5    72    89      0    18
Run Code Online (Sandbox Code Playgroud)


Ice*_*can 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
Run Code Online (Sandbox Code Playgroud)

说明:

  • rleid(x)给出每个元素的ID(整数),x指示该元素是哪个"run",其中"run"表示相邻相等值的序列.
  • dt[, <code>, by = rle(x)]分区dt根据rleid(x)并计算<code>每个dt行的子集.结果堆叠在一起data.table.
  • .N 是给定子集中的元素数
  • .I 是与子集对应的行号的向量
  • firstlast给出向量的第一个和最后一个元素
  • .(<stuff>) 是相同的 list(<stuff>)

    rleid函数,by括号内分组,.N和.I符号,firstlast功能是的一部分data.table封装.