每隔5分钟汇总列值并创建一个新的数据框

时间:2018-08-25 10:36:16

标签: r dataframe aggregate

我的数据框为:

           T1            T2           T3             timestamp
          45.37        44.48            13 2015-11-05 10:23:00
          44.94        44.55         13.37 2015-11-05 10:24:00
          45.32        44.44         13.09 2015-11-05 10:27:00
          45.46        44.51         13.29 2015-11-05 10:28:00
          45.46        44.65         13.18 2015-11-05 10:29:16
          45.96        44.85         13.23 2015-11-05 10:32:00
          45.52        44.56         13.53 2015-11-05 10:36:00
          45.36        44.62         13.25 2015-11-05 10:37:00

我想创建一个新数据框,其中包含基于timestamp列以5分钟为间隔聚合的T1,T2和T3的值。我确实遇到过aggregate,并且似乎使用了其中一列来分组/汇总其他列中的对应值。

如果没有行具有超过5分钟间隔的值,则代表NA的行。我还喜欢另一列,该列指示用于在5分钟间隔内求平均值的数字项。

正在R中寻找最有效的方法。谢谢

1 个答案:

答案 0 :(得分:1)

首先确保时间戳列为date.time列。如果该行已经是这种格式,则可以跳过。

df1$timestamp <- as.POSIXct(df1$timestamp)

xts具有一些用于处理时间序列的出色功能。特别适用于滚动功能或时间汇总功能。在这种情况下,period.apply可以提供帮助。

library(xts)

# create xts object. Be sure to exclude the timestamp column otherwise you end up with a character matrix. 
df1_xts <- as.xts(df1[, -4], order.by = df1$timestamp)

# sum per 5 minute intervals
df1_xts_summed <- period.apply(df1_xts, endpoints(df1_xts, on = "minutes", k = 5), colSums)

# count rows per 5 minute interval and add to data
df1_xts_summed$nrows <- period.apply(df1_xts$T1, endpoints(df1_xts, on = "minutes", k = 5), nrow)

df1_xts_summed 

                        T1     T2    T3 nrows
2015-11-05 10:24:00  90.31  89.03 26.37     2
2015-11-05 10:29:16 136.24 133.60 39.56     3
2015-11-05 10:32:00  45.96  44.85 13.23     1
2015-11-05 10:37:00  90.88  89.18 26.78     2

如果您希望将其全部恢复为data.frame:

df_final <- data.frame(timestamp = index(df1_xts_summed), coredata(df1_xts_summed))
df_final

            timestamp     T1     T2    T3 nrows
1 2015-11-05 10:24:00  90.31  89.03 26.37     2
2 2015-11-05 10:29:16 136.24 133.60 39.56     3
3 2015-11-05 10:32:00  45.96  44.85 13.23     1
4 2015-11-05 10:37:00  90.88  89.18 26.78     2

编辑,如果您希望将所有内容都以5分钟为四舍五入为时间戳,则需要执行以下操作:

第一步是考虑到时间戳的开始分钟,以5分钟间隔替换时间戳。为此,我使用lubridate软件包中的ceiling_date,并将时间戳的第一个值与时间戳的第一个值的上限之间的差添加到该值。这将返回每个间隔的最后一个值。 (如果要使用间隔的开始,则需要使用floor_date

df1$timestamp <- lubridate::ceiling_date(df1$timestamp, "5 mins") + difftime(lubridate::ceiling_date(first(df1$timestamp), "5 mins"), first(df1$timestamp), unit = "secs")

接下来,与之前相同的xts代码将返回相同的数据,但是时间戳现在是5分钟间隔的最后一个值。

df1_xts <- as.xts(df1[, -4], order.by = df1$timestamp)
df1_xts_summed <- period.apply(df1_xts, ep, colSums)
df1_xts_summed$nrows <- period.apply(df1_xts$T1, endpoints(df1_xts, on = "minutes", k = 5), nrow)
df_final <- data.frame(timestamp = index(df1_xts_summed), coredata(df1_xts_summed))
df_final

            timestamp     T1     T2    T3 nrows
1 2015-11-05 10:27:00  90.31  89.03 26.37     2
2 2015-11-05 10:32:00 136.24 133.60 39.56     3
3 2015-11-05 10:37:00  45.96  44.85 13.23     1
4 2015-11-05 10:42:00  90.88  89.18 26.78     2

数据:

df1 <- structure(list(T1 = c(45.37, 44.94, 45.32, 45.46, 45.46, 45.96, 
45.52, 45.36), T2 = c(44.48, 44.55, 44.44, 44.51, 44.65, 44.85, 
44.56, 44.62), T3 = c(13, 13.37, 13.09, 13.29, 13.18, 13.23, 
13.53, 13.25), timestamp = c("2015-11-05 10:23:00", "2015-11-05 10:24:00", 
"2015-11-05 10:27:00", "2015-11-05 10:28:00", "2015-11-05 10:29:16", 
"2015-11-05 10:32:00", "2015-11-05 10:36:00", "2015-11-05 10:37:00"
)), class = "data.frame", row.names = c(NA, -8L))