根据R数据帧中条件的连续出现获得总持续时间

时间:2019-07-03 12:15:36

标签: r dataframe datetime rstudio

我有一个这样的数据框。我想找到v1或v2大于110的持续时间。

timestamp              v1     v2
    14-05-2019 04:28    112.2   111.0
    14-05-2019 04:30    112.2   110.9
    14-05-2019 04:39    101.4   101.8
    14-05-2019 04:40    108.0   108.8
    14-05-2019 04:45    101.1   101.5
    14-05-2019 04:46    100.8   101.2
    14-05-2019 05:32    111.6   111.5
    14-05-2019 05:36    111.5   111.5
    14-05-2019 05:39    111.5   111.5
    14-05-2019 05:41    111.5   111.5
    14-05-2019 05:46    111.5   111.4
    14-05-2019 05:46    111.5   111.3
    14-05-2019 05:47    111.5   111.3
    14-05-2019 05:51    111.2   111.2
    14-05-2019 05:56    111.2   111.2
    14-05-2019 05:57    111.2   111.2

我的代码:

str = 0
end = 0
dur = 0
diff = 0
for (i in (1:norws(x))) {
  if((x['v1'][i,] >=110) || (x['v2'][i,] >=110)){
    if((str !=0) && (i-str == 1)){
      str = i}else{
        str = i
        end = i - 1
      }}
  if((str<end) && (end != 0)){
    diff =  as.numeric(x[end,1] - x[str,1],units="mins")
    dur = dur + diff
  }}
print(dur)

我想获取v1或v2大于110的连续数据的持续时间。 开始和结束都相同,不考虑它们,或者相差0秒。   我将在这里得到两套:

14-05-2019 04:28    112.2   111.0
14-05-2019 04:30    112.2   110.9

这里时间是2分钟14-05-2019 04:30-14-05-2019 04:28 同样,

14-05-2019 05:32    111.6   111.5
14-05-2019 05:36    111.5   111.5
14-05-2019 05:39    111.5   111.5
14-05-2019 05:41    111.5   111.5
14-05-2019 05:46    111.5   111.4
14-05-2019 05:46    111.5   111.3
14-05-2019 05:47    111.5   111.3
14-05-2019 05:51    111.2   111.2
14-05-2019 05:56    111.2   111.2
14-05-2019 05:57    111.2   111.2

这里的时间是25分钟。即,14-05-2019 05:57-14-05-2019 05:32 所以,我总共得到:27分钟

1 个答案:

答案 0 :(得分:1)

这是您的问题的一种data.table方法。

它使用data.table::rleid()根据条件v1 or v2 > 110创建组。然后,通过从每个组的最后一个时间戳减去每个组的第一个时间戳,总结在此条件有效的行上。这样会导致按组列出的扩散时间的duration列。

或者,您可以计算所有持续时间的总和。 format()用于将答案输出为字符串,而不是使用difftime。

样本数据

library(data.table)
DT <- fread("timestamp              v1     v2
14-05-2019T04:28    112.2   111.0
14-05-2019T04:30    112.2   110.9
14-05-2019T04:39    101.4   101.8
14-05-2019T04:40    108.0   108.8
14-05-2019T04:45    101.1   101.5
14-05-2019T04:46    100.8   101.2
14-05-2019T05:32    111.6   111.5
14-05-2019T05:36    111.5   111.5
14-05-2019T05:39    111.5   111.5
14-05-2019T05:41    111.5   111.5
14-05-2019T05:46    111.5   111.4
14-05-2019T05:46    111.5   111.3
14-05-2019T05:47    111.5   111.3
14-05-2019T05:51    111.2   111.2
14-05-2019T05:56    111.2   111.2
14-05-2019T05:57    111.2   111.2")

#create timestamps
DT[, timestamp := as.POSIXct( timestamp, format = "%d-%m-%YT%H:%M" )]

代码

#create groups based on v1|v2 > 110
DT[, group_id := rleid( v1 > 110 | v2 > 110 ) ][]
#group by group_id, only on rows where v1 or v2 > 110
DT[ v1 > 110 | v2 > 110, ][, .(duration = max(timestamp) - min(timestamp) ), by = .(group_id)]

输出

#    group_id duration
# 1:        1   2 mins
# 2:        3  25 mins

替代摘要

将最后一行代码替换为:

format( 
  sum( 
    DT[ v1 > 110 | v2 > 110, ][, .(duration = max(timestamp) - min(timestamp) ), by = .(group_id)]$duration 
  )
)

给出所有“组”的总数。

#27 mins

根据评论中的问题进行更新

要包括每个期间的开始和结束,请使用:

DT[ v1 > 110 | v2 > 110, ][, .(start = min(timestamp),
                               end = max(timestamp),
                               duration = max(timestamp) - min(timestamp) ), 
                           by = .(group_id)][,group_id := NULL]

#                  start                 end duration
# 1: 2019-05-14 04:28:00 2019-05-14 04:30:00   2 mins
# 2: 2019-05-14 05:32:00 2019-05-14 05:57:00  25 mins