使用时间戳进行范围选择

时间:2013-01-24 16:09:39

标签: r timestamp dataframe

您好我的数据框组织如下例所示。我有一个时间戳,一个分组变量,以及几个带有每个时间戳数值的变量。

# dput of subset of data
structure(list(TIMESTAMP = structure(1:15, .Label = c("1/1/2012 11:00", 
"1/1/2012 12:00", "1/1/2012 13:00", "1/1/2012 14:00", "1/1/2012 15:00", 
"1/2/2012 11:00", "1/2/2012 12:00", "1/2/2012 13:00", "1/2/2012 14:00", 
"1/2/2012 15:00", "4/7/2012 11:00", "4/7/2012 12:00", "4/7/2012 13:00", 
"4/7/2012 14:00", "4/7/2012 15:00"), class = "factor"), P = c(992.4, 
992.4, 992.4, 992.4, 992.4, 992.4, 992.4, 992.4, 992.4, 992.4, 
239, 239, 239, 239, 239), WS = c(4.023, 3.576, 4.023, 6.259, 
4.47, 3.576, 3.576, 2.682, 4.023, 3.576, 2.682, 3.129, 2.682, 
2.235, 2.682), WD = c(212L, 200L, 215L, 213L, 204L, 304L, 276L, 
273L, 307L, 270L, 54L, 24L, 304L, 320L, 321L), AT = c(16.11, 
18.89, 20, 20, 19.44, 10.56, 11.11, 11.67, 12.22, 11.11, 17.22, 
18.33, 19.44, 20.56, 21.11), FT = c(17.22, 22.22, 22.78, 22.78, 
20, 11.11, 15.56, 17.22, 17.78, 15.56, 24.44, 25.56, 29.44, 30.56, 
29.44), H = c(50L, 38L, 38L, 39L, 48L, 24L, 19L, 18L, 16L, 18L, 
23L, 20L, 18L, 17L, 15L), B = c(1029L, 1027L, 1026L, 1024L, 1023L, 
1026L, 1025L, 1024L, 1023L, 1023L, 1034L, 1033L, 1032L, 1031L, 
1030L), FM = c(14.9, 14.4, 14, 13.7, 13.6, 13.1, 12.8, 12.3, 
12, 11.7, 12.8, 12, 11.4, 10.9, 10.4), GD = c(204L, 220L, 227L, 
222L, 216L, 338L, 311L, 326L, 310L, 273L, 62L, 13L, 312L, 272L, 
281L), MG = c(8.047, 9.835, 10.28, 13.41, 11.18, 9.388, 8.941, 
8.494, 9.835, 10.73, 6.706, 7.153, 8.047, 8.047, 7.6), SR = c(522L, 
603L, 604L, 526L, 248L, 569L, 653L, 671L, 616L, 487L, 972L, 1053L, 
1061L, 1002L, 865L), WS2 = c(2.235, 3.576, 4.47, 4.47, 5.364, 
4.023, 2.682, 3.576, 3.576, 4.023, 3.129, 3.129, 3.576, 2.682, 
3.129), WD2 = c(200L, 201L, 206L, 210L, 211L, 319L, 315L, 311L, 
302L, 290L, 49L, 39L, 15L, 348L, 329L)), .Names = c("TIMESTAMP", 
"P", "WS", "WD", "AT", "FT", "H", "B", "FM", "GD", "MG", "SR", 
"WS2", "WD2"), class = "data.frame", row.names = c(NA, -15L))

我正在努力找出处理未来操作的时间戳的最佳方法。我读过lubridate(例如here),zooPOSIXt。但是,我觉得可能有一些r / timestamp trickery ,我不知道这会使时间戳更容易(即我可能不完全理解时间戳)。

最终,我想要创建一个新数据框的效果,该数据框包含某些日期或时间范围内所有这些值的平均值。例如,每个变量的平均值在每天12:00和16:00之间。

执行此类任务时,这三个包中的一个是否优于另一个?你能否指出一个可能做我上面写的平均值的例子或解决方案?或者,这些是否更适合计算(例如某些事物之间的小时数,天数等[例如到达和离开]),或者它们是否可用于处理其他数据框任务的时间戳(如平均)?

2 个答案:

答案 0 :(得分:4)

我正在使用提供的示例数据更新答案。在这篇文章的最后,旧的答案仍然保持不变。

首先,您需要将数据框转换为xts对象。

> data.xts <- as.xts(df[,2:14], as.POSIXct(strptime(df[,1], '%m/%d/%Y %H:%S')))
> data.xts
                        P    WS  WD    AT    FT  H    B   FM  GD     MG   SR   WS2 WD2
2012-01-01 11:00:00 992.4 4.023 212 16.11 17.22 50 1029 14.9 204  8.047  522 2.235 200
2012-01-01 12:00:00 992.4 3.576 200 18.89 22.22 38 1027 14.4 220  9.835  603 3.576 201
2012-01-01 13:00:00 992.4 4.023 215 20.00 22.78 38 1026 14.0 227 10.280  604 4.470 206
2012-01-01 14:00:00 992.4 6.259 213 20.00 22.78 39 1024 13.7 222 13.410  526 4.470 210
2012-01-01 15:00:00 992.4 4.470 204 19.44 20.00 48 1023 13.6 216 11.180  248 5.364 211
2012-01-02 11:00:00 992.4 3.576 304 10.56 11.11 24 1026 13.1 338  9.388  569 4.023 319
2012-01-02 12:00:00 992.4 3.576 276 11.11 15.56 19 1025 12.8 311  8.941  653 2.682 315
2012-01-02 13:00:00 992.4 2.682 273 11.67 17.22 18 1024 12.3 326  8.494  671 3.576 311
2012-01-02 14:00:00 992.4 4.023 307 12.22 17.78 16 1023 12.0 310  9.835  616 3.576 302
2012-01-02 15:00:00 992.4 3.576 270 11.11 15.56 18 1023 11.7 273 10.730  487 4.023 290
2012-04-07 11:00:00 239.0 2.682  54 17.22 24.44 23 1034 12.8  62  6.706  972 3.129  49
2012-04-07 12:00:00 239.0 3.129  24 18.33 25.56 20 1033 12.0  13  7.153 1053 3.129  39
2012-04-07 13:00:00 239.0 2.682 304 19.44 29.44 18 1032 11.4 312  8.047 1061 3.576  15
2012-04-07 14:00:00 239.0 2.235 320 20.56 30.56 17 1031 10.9 272  8.047 1002 2.682 348
2012-04-07 15:00:00 239.0 2.682 321 21.11 29.44 15 1030 10.4 281  7.600  865 3.129 329
> data.xts['T12:00:00/T16:00:00']
                        P    WS  WD    AT    FT  H    B   FM  GD     MG   SR   WS2 WD2
2012-01-01 12:00:00 992.4 3.576 200 18.89 22.22 38 1027 14.4 220  9.835  603 3.576 201
2012-01-01 13:00:00 992.4 4.023 215 20.00 22.78 38 1026 14.0 227 10.280  604 4.470 206
2012-01-01 14:00:00 992.4 6.259 213 20.00 22.78 39 1024 13.7 222 13.410  526 4.470 210
2012-01-01 15:00:00 992.4 4.470 204 19.44 20.00 48 1023 13.6 216 11.180  248 5.364 211
2012-01-02 12:00:00 992.4 3.576 276 11.11 15.56 19 1025 12.8 311  8.941  653 2.682 315
2012-01-02 13:00:00 992.4 2.682 273 11.67 17.22 18 1024 12.3 326  8.494  671 3.576 311
2012-01-02 14:00:00 992.4 4.023 307 12.22 17.78 16 1023 12.0 310  9.835  616 3.576 302
2012-01-02 15:00:00 992.4 3.576 270 11.11 15.56 18 1023 11.7 273 10.730  487 4.023 290
2012-04-07 12:00:00 239.0 3.129  24 18.33 25.56 20 1033 12.0  13  7.153 1053 3.129  39
2012-04-07 13:00:00 239.0 2.682 304 19.44 29.44 18 1032 11.4 312  8.047 1061 3.576  15
2012-04-07 14:00:00 239.0 2.235 320 20.56 30.56 17 1031 10.9 272  8.047 1002 2.682 348
2012-04-07 15:00:00 239.0 2.682 321 21.11 29.44 15 1030 10.4 281  7.600  865 3.129 329

现在您可以使用period.apply,如下面的旧答案所示。

旧答案

您可以为此目的考虑“xts”包。

我会根据你的要求给你一个简短的例子。

假设您的时间序列如下所示,采用xts格式

> head(EURUSD);tail(EURUSD)
                       Open    High     Low   Close
2009-05-01 00:10:00 1.32436 1.32600 1.32436 1.32587
2009-05-01 00:20:00 1.32589 1.32597 1.32430 1.32431
2009-05-01 00:30:00 1.32441 1.32543 1.32432 1.32479
2009-05-01 00:40:00 1.32484 1.32554 1.32482 1.32543
2009-05-01 00:50:00 1.32551 1.32610 1.32532 1.32538
2009-05-01 01:00:00 1.32538 1.32618 1.32462 1.32462
                       Open    High     Low   Close
2009-05-31 23:10:00 1.41175 1.41281 1.41129 1.41262
2009-05-31 23:20:00 1.41258 1.41259 1.41205 1.41215
2009-05-31 23:30:00 1.41206 1.41210 1.41128 1.41132
2009-05-31 23:40:00 1.41132 1.41147 1.41062 1.41093
2009-05-31 23:50:00 1.41102 1.41102 1.41032 1.41077
2009-06-01 00:00:00 1.41077 1.41099 1.41002 1.41052

然后您可以按时间索引过滤数据,如下所示

> EURUSDfiltered <- EURUSD['T12:00:00/T16:00:00']

> tail(EURUSDfiltered,60)
                       Open    High     Low   Close
2009-05-27 14:30:00 1.39063 1.39121 1.38873 1.39094
2009-05-27 14:40:00 1.39098 1.39120 1.38863 1.39075
2009-05-27 14:50:00 1.39079 1.39107 1.38935 1.39020
2009-05-27 15:00:00 1.39016 1.39343 1.38986 1.39286
2009-05-27 15:10:00 1.39286 1.39293 1.38711 1.38898
2009-05-27 15:20:00 1.38898 1.38961 1.38744 1.38824
2009-05-27 15:30:00 1.38824 1.39157 1.38814 1.39148
2009-05-27 15:40:00 1.39145 1.39281 1.39064 1.39248
2009-05-27 15:50:00 1.39245 1.39276 1.39123 1.39143
2009-05-27 16:00:00 1.39145 1.39251 1.39140 1.39231
2009-05-28 12:00:00 1.38708 1.38715 1.38524 1.38565
2009-05-28 12:10:00 1.38563 1.38633 1.38540 1.38594
2009-05-28 12:20:00 1.38596 1.38750 1.38528 1.38691
2009-05-28 12:30:00 1.38691 1.38754 1.38646 1.38710
2009-05-28 12:40:00 1.38721 1.38976 1.38668 1.38910
2009-05-28 12:50:00 1.38913 1.38962 1.38761 1.38775
2009-05-28 13:00:00 1.38777 1.38811 1.38629 1.38680
....
2009-05-28 15:30:00 1.39660 1.39691 1.39584 1.39643
2009-05-28 15:40:00 1.39646 1.39802 1.39616 1.39643
2009-05-28 15:50:00 1.39643 1.39704 1.39574 1.39668
2009-05-28 16:00:00 1.39666 1.39684 1.39423 1.39467
2009-05-29 12:00:00 1.41076 1.41076 1.40890 1.40967
2009-05-29 12:10:00 1.40965 1.41010 1.40870 1.40874
2009-05-29 12:20:00 1.40874 1.41062 1.40870 1.41010
2009-05-29 12:30:00 1.41008 1.41013 1.40844 1.40940
2009-05-29 12:40:00 1.40933 1.41140 1.40886 1.40985
2009-05-29 12:50:00 1.40985 1.41075 1.40887 1.41073
....

一旦过滤了数据,您可以在preiod.apply的帮助下使用endpoints计算某些聚合函数

> ep <- endpoints(EURUSDfiltered, on='days')
> aggValues <- period.apply(EURUSDfiltered, INDEX=ep, FUN=mean)
> aggValues
                        Open     High      Low    Close
2009-05-01 16:00:00 1.326569 1.327338 1.325839 1.326445
2009-05-04 16:00:00 1.329267 1.330415 1.328654 1.329759
2009-05-05 16:00:00 1.338648 1.339428 1.337636 1.338623
2009-05-06 16:00:00 1.331870 1.332957 1.330978 1.331909
2009-05-07 16:00:00 1.339542 1.341126 1.337957 1.339760
2009-05-08 16:00:00 1.347692 1.348982 1.346786 1.347995
2009-05-11 16:00:00 1.359852 1.360683 1.359177 1.359987
2009-05-12 16:00:00 1.365657 1.366473 1.364534 1.365473
2009-05-13 16:00:00 1.360978 1.361865 1.359939 1.360888
2009-05-14 16:00:00 1.358187 1.359207 1.357512 1.358386
2009-05-15 16:00:00 1.356786 1.357672 1.355668 1.356690
2009-05-18 16:00:00 1.349660 1.350412 1.349085 1.349679
2009-05-19 16:00:00 1.360091 1.360750 1.359121 1.360065
2009-05-20 16:00:00 1.373703 1.374888 1.373062 1.373990
2009-05-22 16:00:00 1.399224 1.400354 1.398262 1.399429
2009-05-25 16:00:00 1.399991 1.400309 1.399607 1.399976
2009-05-26 16:00:00 1.393970 1.395064 1.393425 1.394333
2009-05-27 16:00:00 1.392505 1.393589 1.391215 1.392552
2009-05-28 16:00:00 1.391658 1.392870 1.390735 1.391952
2009-05-29 16:00:00 1.411398 1.412516 1.410404 1.411468

更新:回应以下评论

?.subset.xts的进一步研究表明,When a raw character vector is used for the i subset argument, it is processed as if it was ISO-8601 compliant.http://en.wikipedia.org/wiki/ISO_8601提及T前缀用于指定时间

答案 1 :(得分:1)

我认为最有帮助的过程是将[TIMESTAMP]数据变为分组变量。然后,我建议使用众多数据摘要包中的一个来创建报告。我个人的偏好是使用'plyr'包来完成这两个任务,我在这个例子中使用它。

第1步:使用'as.POSIXct'函数将时间戳数据转换为POSIX日期时间,以便与各种日期时间函数一起使用。不使用任何参数来简单地转换数据而无需任何调整。

data$TIMESTAMP <- as.POSIXct(data$TIMESTAMP)

更新:由于时间不是明确的降序格式(即YYYY / MM / DD HH:MM:SS),'as.POSIXct'函数不会能够快速转换数据。仅在使用明确格式时才使用'as.POSIXct'。对于其他安排,使用'strptime'函数,指定当前格式如下:

data$TIMESTAMP <- strptime(data$TIMESTAMP, "%m/%d/%Y %H:%M")

这告诉'strptime'函数当前使用的是什么格式,并导出与POSIX兼容的日期时间。除非您当前的数据不是字符串,否则不应该使用'as.character'函数。

第2步:使用'plyr'函数'ddply'(获取数据帧并返回数据帧)来创建一个新的变量,以便在分组中使用。使用'format'函数从TIMESTAMP值中提取所需的数据。查看可用格式的“格式”文档。在这种情况下,以下是创建[MONTH]变量的方法:

library(plyr)
data <- ddply(data, .(TIMESTAMP), mutate, MONTH=format(TIMESTAMP, "%m")

第3步:使用'plyr'函数'ddply'按新变量汇总数据。

ddply(data, .(MONTH), summarize, V1_AVG=mean(V2), V2_AVG=mean(V2))

如果你想通过第二个变量(如[GROUP])进行汇总,只需将其包含在第二个函数变量中,如下所示:

ddply(data, .(MONTH, GROUP), summarize, V1_AVG=mean(V2), V2_AVG=mean(V2))

从技术上讲,你可以在一个声明中做到这一点,但经验告诉我谨慎。我建议单独完成每一步,以确保没有任何事情搞砸。

只要您的时间戳已转换为POSIX日期时间,您就可以通过这样的方式解析您喜欢的数据。 'plyr'包对于这样的东西非常灵活。

更新:根据OP的要求,我将介绍如何进行相同的计算,但仅使用12p和4p之间的数据。您实际上不必使用任何特定的包来像这样对数据进行子集化,因为它是一个直接的数据过滤器。只需更改输入'ddply'函数的数据集,如下所示:

# Use one of the following lines, which both do the same thing.
# I'm just including both as different examples of logic that can be used.
data_Subset <- data[format(data$TIMESTAMP, "%H") >= 12 & format(data$TIMESTAMP, "%H") < 16,]
data_Subset <- data[format(data$TIMESTAMP, "%H") %in% 12:15,]

# Then summarize using the new data frame as an input
ddply(data_Subset, .(MONTH, GROUP), summarize, V1_AVG=mean(V2), V2_AVG=mean(V2))

这里,我们过滤数据框只显示小时(%H)等于12到15的行(包括所有列)。这实际上包括从12:00到15:59的所有时间。如果你开始涉及非常大的数据集,你可能需要寻找其他解决方案(比如'data.table'包),否则,这是你最快的选择。

同样,这只能起作用,因为我们已将日期时间转换为与POSIX兼容的日期时间。