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

3

I have a dataframe as:

           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

我想创建一个新的数据框,其中包含基于“时间戳”列聚合的T1、T2和T3值的5分钟间隔。我找到了“aggregate”的相关资料,它似乎使用其中一列来分组/聚合其他列中相应的值。
如果没有行在5分钟间隔内具有值,则用行表示“NA”。我还想添加另一列,指示用于计算5分钟间隔平均值的项目数。
在R语言中最有效的方法是什么?谢谢。

请提供数据集(使用dput),并提供所需的输出。 - ashleych
1个回答

3

首先,确保时间戳列是日期时间格式的。如果已经是该格式,则可以跳过此行。

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

如果你希望将所有内容转换为数据框:
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分钟为间隔进行四舍五入,则需要执行以下操作:

第一步是使用lubridate包中的ceiling_date函数将时间戳替换为5分钟间隔,考虑时间戳的起始分钟。然后,将第一个时间戳值与其上限之间的差值添加到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))

感谢您的回答。我希望每五分钟得到一个值。在您的回答中,第二个值出现在10:29:16,第三个值出现在10:32:00。我希望下一个值在10:34:00或之后出现。基本上,我想做的是将不等间隔的时间序列转换为5分钟间隔的等间隔时间序列。 - Balki
Period.apply返回间隔中已知的最后一个值。10:31和10:35之间的5分钟间隔中,10:32是最后一个可用值。但是,如果您想返回5分钟间隔中的所有内容,您真的应该指定您期望的输出。有floor函数,但它们会将所有内容向下舍入到最近的指定周期。例如,如果是5分钟,则您的数据将从10:20开始,而不是10:23。这可能并不完全符合您的要求。 - phiver
我添加了代码以返回5分钟间隔的最后日期时间。 - phiver
#phiver,我很感激你在这里的回答,但我想知道是否有其他解决方案,不需要使用xts文件。我使用xts的问题在于,我有一些字符数据(特别是股票代码),似乎无法使用xts文件(这有点讽刺,因为我认为xts文件经常用于投资情况)。你有什么想法吗? - W Barker
@WBarker,你可以尝试使用tidyquant包中的tq_transmute函数。xts通常用于列表对象和lapply以处理多个股票代码。有多个SO答案可以向你展示如何操作。如果需要进一步帮助,请创建一个包含样例和期望输出的SO问题。 - phiver

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