首页 > 解决方案 > 以 5 分钟的间隔聚合列值并创建一个新的数据框

问题描述

我有一个数据框:

           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 分钟间隔,则表示NAs 的行。我还喜欢另一列,该列指示用于在 5 分钟间隔内进行平均的项目数。

寻找一种最有效的方法R。谢谢

标签: rdataframeaggregate

解决方案


首先确保时间戳列是 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 分钟间隔,同时考虑时间戳的起始分钟数。为此,我使用ceiling_datelubridate 包中的 lubridate 包,并将时间戳的第一个值与时间戳的第一个值的上限之间的差异添加到其中。这将返回每个间隔的最后一个值。(如果你想使用间隔的开始,你需要使用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))

推荐阅读