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长的零序列.然后,我们计算starts和ends子集或全部重复序列的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)
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)
通过使用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)
如果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 是与子集对应的行号的向量first并last给出向量的第一个和最后一个元素.(<stuff>) 是相同的 list(<stuff>)
的rleid函数,by括号内分组,.N和.I符号,first和last功能是的一部分data.table封装.