使用R对时间序列中的事件进行分组

9
我一直在记录日志,试图向Comcast Business说明他们在我的办公室中断服务的频率。我将ping响应时间记录到文件中,然后用R解析该文件。在日志文件中,值为1000表示ping超时。我的脚本每5秒记录一次ping。因此,如果我的Comcast服务中断了30秒,那么就会产生大约6个值为1000的日志条目。我想以这样的方式解析我的日志,以便创建一个摘要表格,显示每次中断开始的时间和持续时间。有什么好的方法可以做到这一点?
以下是今天的一些示例数据和说明我的时间序列的一些图形:
require(xts)
outFile <- "http://pastebin.com/raw.php?i=SJuMQ9rD"
pingLog <- read.csv(outFile, header=FALSE, 
     col.names = c("time","ms"), 
     colClasses=c("POSIXct", "numeric"))
xPingLog <- as.xts(pingLog$ms, order.by=pingLog$time)
outages <- subset(pingLog, ms==1000)
xOutages <- as.xts(outages$ms, order.by=outages$time)

par(mfrow=c(2,1))
plot(xPingLog)
plot(outages)
outages
1个回答

12

你一定会喜欢游程长度编码,也叫做rle

offline <- ifelse(pingLog$ms==1000, TRUE, FALSE)
rleOffline <- rle(offline)

offlineTable <- data.frame(
    endtime = pingLog$time[cumsum(rleOffline$lengths)],
    duration = rleOffline$lengths * 5,
    offline = rleOffline$values
)

结果为:

offlineTable

              endtime duration offline
1 2011-11-20 13:20:19     1030   FALSE
2 2011-11-20 13:20:35        5    TRUE
3 2011-11-20 13:24:37      240   FALSE
4 2011-11-20 13:25:57       25    TRUE
5 2011-11-20 13:53:28     1640   FALSE

为什么这个代码有效?

首先构建一个逻辑向量来指示在线与离线。使用 ifelse 函数非常方便。

offline <- ifelse(pingLog$ms==1000, TRUE, FALSE)

然后使用rle计算运行长度编码:

rle(offline)
Run Length Encoding
  lengths: int [1:5] 206 1 48 5 328
  values : logi [1:5] FALSE TRUE FALSE TRUE FALSE

这个表格告诉我们TRUE或FALSE连续出现的次数,以及每个连续区间的长度。在这个例子中,第一个连续区间是206个周期且值为FALSE(也就是在线上206*5=1030秒)。

最后一步是使用rle信息对原始的pingLog进行索引以找到时间。额外的魔法是使用cumsum计算运行长度的累积和。这在现实世界中意味着每个区间结束时的索引位置。


这是一个非常方便的函数! - Ryogi
太棒了!这对我来说也是一个新函数。 - JD Long
1
ifelse(pingLog$ms==1000, TRUE, FALSE) 可以缩短为 pingLog$ms==1000 - tstenner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接