查找数据中连续递减值的行数

Ale*_*der 8 diff r dplyr

我需要从数据中检测连续减少数量的长度为5的第一个序列的第一个元素.这里有一个类似的帖子,但当我申请我的数据时,它失败了.

set.seed(201)  
az <- c(sort(runif(10,0,0.9),decreasing = T),sort(runif(3,-0.3,0),decreasing = T),sort(runif(3,-0.3,0),decreasing = F),sort(runif(4,-0.3,0),decreasing = T),sort(runif(4,-0.3,0),decreasing = F),sort(runif(6,-0.3,0),decreasing = T))   
tz <- seq(1,length(az))
df <- data.frame(tz,az=round(az,2))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在上图中,它将在tz = 25附近.

帖子说这个功能需要改进,到目前为止我无法得到我想要的结果!

  getFirstBefore<-function(x,len){
    r<-rle(sign(diff(x)))
    n<-which(r$lengths>=len & r$values<0)
    if(length(n)==0)
      return(-1)
    1+sum(r$lengths[seq_len(n[1]-1)])
  }

df1 <- df%>%
mutate(cns_tz=getFirstBefore(az,5))

 tz    az cns_tz
#1   1  0.56      4
#2   2  0.55      4
#3   3  0.33      4
#4   4  0.33      4
#5   5  0.26      4
#6   6  0.15      4
#7   7  0.12      4
#8   8  0.09      4
#9   9  0.04      4
#10 10  0.04      4
#11 11 -0.10      4
#12 12 -0.12      4
#13 13 -0.16      4
#14 14 -0.16      4
#15 15 -0.14      4
#16 16 -0.14      4
#17 17 -0.13      4
#18 18 -0.15      4
#19 19 -0.22      4
#20 20 -0.30      4
#21 21 -0.12      4
#22 22 -0.12      4
#23 23 -0.11      4
#24 24 -0.07      4
#25 25 -0.05      4
#26 26 -0.09      4
#27 27 -0.10      4
#28 28 -0.15      4
#29 29 -0.17      4
#30 30 -0.22      4
Run Code Online (Sandbox Code Playgroud)

Wie*_*314 6

我会对每5个连续值进行排序,看看它是否与未排序的数据匹配.然后找到这样一场比赛的第一次出现:

set.seed(123)
test <- rnorm(100)

decr <- sapply(seq_along(test),function(x){all(sort(test[x:(x+5)],decreasing = T) == test[x:(x+5)])})
firstdecr <- min(which(decr)):(min(which(decr))+5)
plot(test)
lines(firstdecr, test[firstdecr], col="red")
Run Code Online (Sandbox Code Playgroud)

只有缺陷,我才能看到5值时代中是否有相同的值,但你也可以测试它.


akr*_*run 4

我们可以使用rleid来自data.table

library(data.table)
n <- 5
v1 <- setDT(df)[sign(az)<0,  .I[which(.N==n)] , rleid(c(1, sign(diff(az))))]$V1[1L]
v1
#[1] 26
df[, cnz_tz := v1]
Run Code Online (Sandbox Code Playgroud)

或者另一个选择shiftReduce

setDT(df)[, cnz_tz := .I[Reduce(`&`, shift((az - shift(az, fill=az[1])) < 0,
                            0:4, type = "lead", fill=FALSE)) & sign(az) < 0][1]]
Run Code Online (Sandbox Code Playgroud)

我们还可以用rleiddplyr

library(dplyr)
v1 <- df %>% 
         group_by(rl= rleid(c(1, sign(diff(az))))) %>% 
         mutate(rn =  sign(az) < 0 & n()==5) %>% 
        .$rn %>%
         which() %>% 
         head(., 1)
v1
#[1] 26
df %>%
   mutate(cnz_tz = v1)
Run Code Online (Sandbox Code Playgroud)