将1分钟的数据汇总成5分钟的平均数据

时间:2014-03-05 16:28:54

标签: r date

我的问题是将每1分钟收集的数据汇总到5分钟的平均值。

DeviceTime         Concentration
6/20/2013 11:13       
6/20/2013 11:14
6/20/2013 11:15
6/20/2013 11:16
6/20/2013 11:17
6/20/2013 11:18
6/20/2013 11:19
6/20/2013 11:20
6/20/2013 11:21
6/20/2013 11:22
6/20/2013 11:23
6/20/2013 11:24
6/20/2013 11:25
6/20/2013 11:26
6/20/2013 11:27
6/20/2013 11:28

...

我想要的结果是:

DeviceTime             Concentration
6/20/2013 11:15
6/20/2013 11:20
6/20/2013 11:25
6/20/2013 11:30
6/20/2013 11:35
...

5分钟的平均值只是过去五分钟内浓度的简单平均值。

3 个答案:

答案 0 :(得分:19)

如果你的数据没有在一个漂亮的5分钟挂钟边界上开始(如示例数据中所示--11:13),请注意cut()将根据第一个时间戳创建断点认定。这可能不是我们通常想要的。实际上,您的示例输出表明这不是您想要的。

这是cut()的作用:

df <- read.table(header=TRUE, sep=",", stringsAsFactors=FALSE, text="
DeviceTime,Concentration
6/20/2013 11:13,1
6/20/2013 11:14,1
6/20/2013 11:15,2
6/20/2013 11:16,2
6/20/2013 11:17,2
6/20/2013 11:18,2
6/20/2013 11:19,2
6/20/2013 11:20,3
6/20/2013 11:21,3
6/20/2013 11:22,3
6/20/2013 11:23,3
6/20/2013 11:24,3
6/20/2013 11:25,4")
df$DeviceTime <- as.POSIXct(df$DeviceTime, format="%m/%d/%Y %H:%M")

cut(df$DeviceTime, breaks="5 min")
 [1] 2013-06-20 11:13:00 2013-06-20 11:13:00 2013-06-20 11:13:00
 [4] 2013-06-20 11:13:00 2013-06-20 11:13:00 2013-06-20 11:18:00
 [7] 2013-06-20 11:18:00 2013-06-20 11:18:00 2013-06-20 11:18:00
[10] 2013-06-20 11:18:00 2013-06-20 11:23:00 2013-06-20 11:23:00
[13] 2013-06-20 11:23:00

means <- aggregate(df["Concentration"], 
                   list(fiveMin=cut(df$DeviceTime, "5 mins")),
                   mean)
means
              fiveMin Concentration
1 2013-06-20 11:13:00      1.600000
2 2013-06-20 11:18:00      2.600000
3 2013-06-20 11:23:00      3.333333

请注意,means的第一行(11:13:00条目)是df的前5行的平均值,其时间为11:13至11:17 - - 即直到11:18的下一个切入/断点之前。

如果您使用cut(),您将获得与dplyr相同的结果(即@ lukeA&#39;答案):

df %>%
  group_by(DeviceTime = cut(DeviceTime, breaks="5 min")) %>%
  summarize(Concentration = mean(Concentration))
Source: local data frame [3 x 2]

           DeviceTime Concentration
1 2013-06-20 11:13:00      1.600000
2 2013-06-20 11:18:00      2.600000
3 2013-06-20 11:23:00      3.333333

xts包似乎打破了挂钟时间:

require(xts)
df.xts <- xts(df$Concentration, df$DeviceTime)
means.xts <- period.apply(df.xts, endpoints(df.xts, "mins", k=5), mean)
means.xts
                    [,1]
2013-06-20 11:14:00    1
2013-06-20 11:19:00    2
2013-06-20 11:24:00    3
2013-06-20 11:25:00    4

时间值始终是在5分钟窗口中找到的最后一次输入。如果要报告期末结束的时间,可以使用align.time()将时间索引列向上舍入下一个5分钟的边界:

means.rounded <- align.time(means.xts, 5*60)
means.rounded
                    [,1]
2013-06-20 11:15:00    1
2013-06-20 11:20:00    2
2013-06-20 11:25:00    3
2013-06-20 11:30:00    4

如果要报告期间开始的时间,也可以向下舍入。但是你需要先定义自己的函数(我在Cross Validated找到):

align.time.down = function(x,n) {
    index(x) = index(x) - n
    align.time(x,n)
}
means.rounded.down <- align.time.down(means.xts, 5*60)
means.rounded.down
                    [,1]
2013-06-20 11:10:00    1
2013-06-20 11:15:00    2
2013-06-20 11:20:00    3
2013-06-20 11:25:00    4

另一个不使用xts包的解决方案,而不是floor(),如下所示:

df$DeviceTimeFloor <- as.POSIXct(floor(as.numeric(df$DeviceTime) / (5 * 60)) * (5 * 60), origin='1970-01-01')
meansFloor <- aggregate(Concentration ~ DeviceTimeFloor, df, mean)
meansFloor
      DeviceTimeFloor Concentration
1 2013-06-20 11:10:00             1
2 2013-06-20 11:15:00             2
3 2013-06-20 11:20:00             3
4 2013-06-20 11:25:00             4

我更愿意报告5分钟间隔的开始时间 - floor()对此有好处。因为,如果我按小时报告聚合,我希望2013-06-20 11:00:00的时间戳包含11:00:00 - 11:59:59而不是10:00:00的数据 - 10:59:59。

如果您希望报告时间间隔的结束时间,则可以使用ceiling()代替floor()。但请注意,时间戳11:01 - 11:05将由ceiling()转换为(并因此分组)在11:05。相反,floor()将11:00 - 11:04转换为11:00。

所以他们每组都有一组不同的观察结果。 xts包会将同一组观察结果分组为floor(),但它会报告最后一次观察的最后一个时间戳。周期。

答案 1 :(得分:12)

使用dplyr包并假设您的数据存储在名为df的数据框中:

require(dplyr)
df %>%
  group_by(DeviceTime = cut(DeviceTime, breaks="5 min")) %>%
  summarize(Concentration = mean(Concentration))

答案 2 :(得分:1)

我想说的是,最简单,最干净的方法是使用CustomTypelubridate软件包。

dplyr

这里唯一的问题是,它仅适用于适合一个小时的值,即:1、2、3、4、5、6、10、12、15、20、30、60分钟。但是对于这些来说,它是完美的:-)