计算R中时间序列中某个条件的恢复时间

计算R中时间序列中某个条件的恢复时间,r,time-series,data.table,R,Time Series,Data.table,我想计算从不满足条件到再次满足条件的天数,在R中的每日数据时间序列中 玩具数据: day <- data.frame( date = seq.POSIXt( from = ISOdatetime(2017,07,01,0,0,0), to = ISOdatetime(2017,08,26,0,0,0), by = "1 day" )) var <- c(5,6,5,5,0,0,0,0,0,1,1,2,3,3,4,3,4,5,4,5,5,4,5,4,0,1

我想计算从不满足条件到再次满足条件的天数,在R中的每日数据时间序列中

玩具数据:

day <- data.frame(
  date = seq.POSIXt(
    from = ISOdatetime(2017,07,01,0,0,0),
    to = ISOdatetime(2017,08,26,0,0,0),
    by = "1 day" ))

var <- c(5,6,5,5,0,0,0,0,0,1,1,2,3,3,4,3,4,5,4,5,5,4,5,4,0,1,1,2,3,4,5,5,5,4,4,4,4,5,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,1,1,0,0)

ts = cbind(day, var)
由于var从不在数据集结束时“恢复”,因此我希望它不被标识为恢复期,或者给定0天的恢复时间

我试过这个:

ifelse(ts$var >3, 0 ,(ifelse(ts$var>0 & ts$var<4, 1, 0)))
ifelse(ts$var>3,0,(ifelse(ts$var>0&ts$var编辑
-我不认为如果var做了这样的事情,它的行为会像你期望的那样

[…0,1,2,1,0,2,4,…]

但可能会适应处理这种情况

原始答案

我还没有测试过这么多,我建议检查它是否适用于更奇怪的情况(例如,var都是零,在周期边界开始或结束,其他角点情况…)

#如果零位于另一个零之前,则忽略这些零
s x],1)-x)

这里的方法是识别周期的所有可能的起点和终点,然后找到每个起点之后出现的第一个终点并取其差值。一个简单的循环或者甚至一个聪明的正则表达式可能是一个很好的替代方法。

这里有一个使用
rleid()的替代方法
函数通过零值和非零值的连续条纹从包到组。然后,它在每组中找到第一次出现值>3的位置:

library(data.table)
setDT(ts)[, if (.GRP > 1) first(which(var > 3)), rleid(var == 0)]
跳过第一个组,因为它要么是一条零条纹,要么没有前面的零值

这种方法即使在以下情况下也有效:

因此,它已经认识到,在最终零点之后有2天的恢复期

为完整起见,如果序列0、1、2、1、0被认为还包括3天的恢复期,尽管其未达到大于3的值:

setDT(ts)[, if (.GRP > 1) if (all(var %between% c(1, 3))) .N else first(which(var > 3)), 
          rleid(var == 0)]

这里,如果所有值都在1和3之间,则两个零之间的所有天数都会被计算。

谢谢!这非常有效。它与编辑中的数字的行为方式实际上正是我希望它的行为方式-它会一直计数,直到满足条件。我将对它进行更多的测试,但我认为它很好地满足了我的需要。太好了!我希望它能继续does-我担心的是,在编辑示例中,它将计算两个恢复期,一个是从第一个0到4,另一个是从第二个0到4。是的,我现在意识到了这一点。我正在研究一个解决方案。到目前为止,我有一个sapply fxn,用于确定每个起点/终点之间的时间段是否具有小于4的值:bad=sappy(1:(长度(s)-1),function(x)all(ts$var[c(s[x]:s[x+1])]<4))现在我只需要一种方法将其应用于s向量以消除“bad”恢复期。有什么想法吗?我想我已经知道了:
bad=c(FALSE,sappy(1:(长度(s)-1),function(x)all(ts$var[c(s[x]:s[x+1])<4));s2=s[bad!=TRUE]
library(data.table)
setDT(ts)[, if (.GRP > 1) first(which(var > 3)), rleid(var == 0)]
   rleid V1
1:     3  6
2:     5  5
# append data
var <- c(var, 0,1,2,1,0,2,4)
date = seq.POSIXt(
  from = ISOdatetime(2017,07,01,0,0,0),
  along.with = var,
  by = "1 day" )
ts = data.frame(date, var)

setDT(ts)[, if (.GRP > 1) first(which(var > 3)), rleid(var == 0)]
   rleid V1
1:     3  6
2:     5  5
3:     9  2
setDT(ts)[, if (.GRP > 1) if (all(var %between% c(1, 3))) .N else first(which(var > 3)), 
          rleid(var == 0)]
   rleid V1
1:     3  6
2:     5  5
3:     7  3
4:     9  2