子集连续时间(chron)并聚合它们

时间:2013-07-30 20:58:22

标签: r

我有大量的电压读数数据。我希望确定电压高于阈值的不同时间段的频率。因此,利用电压子集(> = 2V),我希望计算基于1秒采样间隔的电压的连续周期的长度。请参阅以下示例数据:

library(chron)
volts=c(2,3,4,5,6,2,2,3,4,5,5,5)
t=chron(times=c("23:03:20", "23:03:21", "23:03:22", "23:03:23","23:03:24","23:03:25","04:01:50","04:01:51","04:01:52","04:01:53","04:01:54","04:01:55"))
data=data.frame(volts,"time"=t)

这个例子有两个兴趣系列,一个是23:03:20到23:03:25,另一个是04:01:50到04:01:55。

我希望计算这些周期的持续时间和大量数据的平均电压,条件是它们被认为是离散的周期之间有30秒。我怀疑我的答案可能会停留在动物园,我欢迎提出建议。

3 个答案:

答案 0 :(得分:2)

在输出中使用与@BenBolker相同的名称:

library(data.table)
dt = data.table(data)

dt[, time := as.ITime(time)] # easier to deal with

dt[, list(meanvolts = mean(volts), duration = time[.N] - time[1], n = .N),
     by = list(period = 1 + c(0, cumsum(abs(diff(time)) >= 30)))]
#   period meanvolts duration n
#1:      1  3.666667 00:00:05 6
#2:      2  4.000000 00:00:05 6

答案 1 :(得分:1)

zoo可能有一个更有效的解决方案,但是如何:

样本数据(为方便起见重复)

library(chron)
dat <- data.frame(volts=c(2,3,4,5,6,2,2,3,4,5,5,5),
  time=chron(times=c("23:03:20", "23:03:21", "23:03:22", 
             "23:03:23","23:03:24","23:03:25",
              "04:01:50","04:01:51","04:01:52","04:01:53",
              "04:01:54","04:01:55")))

分析:

daysecs <- 3600*24
dd <- c(unclass(diff(dat$time))*daysecs)   ## difference in seconds
## classify jumps to new periods, including day boundaries 
## (I haven't tested this carefully!)
new_per <- !((dd>0 & dd<30) | (dd<0 & dd<(-daysecs+30))) 
dat$period <- 1+c(0,cumsum(new_per)) ## a fairly standard trick
library(plyr)
ddply(dat,.(period),summarise,
      meanvolts=mean(volts),
      duration=tail(time,1)-time[1],
      n=length(volts))

结果:

##   period meanvolts duration n
## 1      1  3.666667 00:00:05 6
## 2      2  4.000000 00:00:05 6

plyr特别不是超快,但我会尝试对你的数据进行测试,看看它是否可以快速恢复,然后让我们了解它的速度(编辑方式)你的问题(“我有600万次电压测量...”)或发布一个链接到这个问题的新问题

答案 2 :(得分:1)

这是一个解决方案xts包。通常我们使用period.apply函数来处理这样的时间序列过程。实际上,我只使用endpoints来创建拆分器索引(每30秒),然后使用经典sapply进行循环。

library(xts)
## creating the `xts` objects.
x.z <- xts(data$volts,
           as.POSIXct(strptime(data$time,format='%H:%M:%S')))

INDEX <- endpoints(x.z,'secs',30)
xx <- sapply(1:(length(INDEX) - 1), function(y) {
  x <- x.z[(INDEX[y] + 1):INDEX[y + 1]]
  data.frame(period=y,
             duration=diff(range(index(x))),
             mm = mean(x),
             len = length(x))
})


t(xx)
     period duration mm       len
[1,] 1      5        4        6  
[2,] 2      5        3.666667 6  

编辑 endpoints如何处理时间索引超过天边界的特殊情况?

创建示例:

## creating xts object index
ii <- as.POSIXct(strptime(data$time,format='%H:%M:%S'))
## here I add  day to simulate day boundary
ii[6]  <- as.POSIXct(ii[6] + as.difftime(1,units='days'))

现在我的时间看起来像是:

    x.z
                    [,1]
2013-07-31 04:01:50    2
2013-07-31 04:01:51    3
2013-07-31 04:01:52    4
2013-07-31 04:01:53    5
2013-07-31 04:01:54    5
2013-07-31 04:01:55    5
2013-07-31 23:59:55    2
2013-07-31 23:59:56    3
2013-07-31 23:59:57    4
2013-07-31 23:59:58    5
2013-07-31 23:59:59    6
2013-08-01 00:00:02    2   ## day boundaries here

应用相同的代码(解决方案的开头)我们得到 3 期间而不是 2预期

 t(xx)
     period duration mm len
[1,] 1      5        4  6  
[2,] 2      4        4  5  
[3,] 3      0        2  1    ## 2013-08-01 00:00:02    2