将时间序列数据从秒数转换为 R 中的小时数
Convert time-series data from seconds to hourly means in R
注意:我已经按照评论中的说明重新设计了之前的问题。
我正在使用三个不同的包,即 dplyr、data.table 和 xts 将我的秒数数据聚合为每小时平均表示。但是,令我惊讶的是,与其他两个相比,xts 的行为有所不同。 xts 的问题是:
- 与其他两个相比,多了一个观察结果
- 计算的小时平均值与其他两个完全不同
这是用于测试目的的压缩代码:
library(xts)
library(data.table)
library(dplyr)
t2 <- as.POSIXct(seq(from = 1438367408, to = 1440959383, by = 30), origin = "1970-01-01")
dframe <- data.frame(timestamp=t2, power=rnorm(length(t2)))
#using xts
x <- xts(dframe$power,dframe$timestamp)
h1 <- period.apply(x, endpoints(x, "hours"), mean)
h1 <- data.frame(timestamp=trunc(index(h1),'hours'), power=coredata(h1))
#using data.table
h2 <- setDT(dframe)[, list(power= mean(power)) ,(timestamp= as.POSIXct(cut(timestamp, 'hours')))]
#using dpylr
h3 <- dframe %>% group_by(timestamp= as.POSIXct(cut(timestamp, 'hour'))) %>% summarise(power=mean(power))
关于大小的输出:
> dim(h1)
[1] 721 2
> dim(h2)
[1] 720 2
> dim(h3)
[1] 720 2
关于每小时的输出意味着:
> head(h1)
timestamp power
1 2015-08-01 00:00:00 0.04485894
2 2015-08-01 01:00:00 -0.02299071
> head(h2) # equals to head(h2)
timestamp power
1: 2015-08-01 00:00:00 0.10057538
2: 2015-08-01 01:00:00 -0.07456292
h1 的额外观察:
> tail(h1)
timestamp power
719 2015-08-30 22:00:00 0.069544538
720 2015-08-30 23:00:00 0.011673835
721 2015-08-30 23:00:00 -0.053858563
很明显,一天的最后一个小时有两次观察。正常应该只有一个。
我的系统信息:
> sessionInfo()
R version 3.2.2 (2015-08-14)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.10.3 (Yosemite)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] dplyr_0.4.3 data.table_1.9.7 xts_0.9-7 zoo_1.7-12
loaded via a namespace (and not attached):
[1] lazyeval_0.1.10 magrittr_1.5 R6_2.1.1 assertthat_0.1 parallel_3.2.2 DBI_0.3.1 tools_3.2.2
[8] Rcpp_0.12.1 grid_3.2.2 chron_2.3-47 lattice_0.20-33
注:
- 原始数据集可在 link
- 我想要一个解决这个问题的方法,因为在我的实现场景中,xts 比剩下的两个快 35 倍
这看起来可能是 endpoints
中的错误,因为您的本地时区与 UTC 的时差不是整小时。如果我将本地时区设置为您的时区,我可以重现该问题。
R> Sys.setenv(TZ="Asia/Kolkata")
R> x <- xts(dframe$power,dframe$timestamp)
R> h <- period.apply(x, endpoints(x, "hours"), mean)
R> head(h)
[,1]
2015-08-01 00:29:31 124.9055
2015-08-01 01:29:31 129.7197
2015-08-01 02:29:31 139.0899
2015-08-01 03:29:32 145.6592
2015-08-01 04:29:32 153.6840
2015-08-01 05:29:32 114.4809
请注意,端点以半小时为增量,而不是在一小时结束时。这是因为 Asia/Kolkata 是 UTC+0530,而 endpoints
会根据以 UTC 表示的时间进行所有计算。
您可以通过将 POSIXct 对象的时区显式设置为 UTC 来避免这种情况。
require(xts)
require(dplyr)
require(data.table)
Sys.setenv(TZ="Asia/Kolkata")
dframe <- read.csv("~/ap601.csv",head=TRUE,sep=",")
# set timezone on POSIXct object
dframe$timestamp <- as.POSIXct(dframe$timestamp, tz="UTC")
#using xts
x <- xts(dframe$power, dframe$timestamp)
h <- period.apply(x, endpoints(x, "hours"), mean)
h1 <- data.frame(timestamp=trunc(index(h),'hours'), power=coredata(h))
# using data.table
h2 <- setDT(dframe)[, list(power= mean(power)) ,(timestamp= cut(timestamp, 'hour'))]
# using dplyr
h3 <- dframe %>% group_by(timestamp= cut(timestamp, 'hour')) %>% summarise(power=mean(power))
all.equal(h1$power, h2$power) # TRUE
all.equal(h1$power, h3$power) # TRUE
这里有一个变通方法,可以在不将 POSIXct 列的时区设置为 UTC 的情况下获得相同的结果。请注意,这可能不适用于夏令时的时区(Asia/Kolkata 不遵守任何 DST)。
基本上,想法是在计算 endpoints
时从当地时间减去半小时,以便基础 UTC 时间与小时对齐。
dframe <- read.csv("~/ap601.csv",head=TRUE,sep=",")
dframe$timestamp <- as.POSIXct(dframe$timestamp)
# subtract half an hour from the index when calculating endpoints
h <- period.apply(x, endpoints(index(x)-3600*0.5, 'hours'), mean)
h1 <- data.frame(timestamp=trunc(index(h),'hours'), power=coredata(h))
all.equal(h1$power, h2$power) # TRUE
all.equal(h1$power, h3$power) # TRUE
注意:我已经按照评论中的说明重新设计了之前的问题。
我正在使用三个不同的包,即 dplyr、data.table 和 xts 将我的秒数数据聚合为每小时平均表示。但是,令我惊讶的是,与其他两个相比,xts 的行为有所不同。 xts 的问题是:
- 与其他两个相比,多了一个观察结果
- 计算的小时平均值与其他两个完全不同
这是用于测试目的的压缩代码:
library(xts)
library(data.table)
library(dplyr)
t2 <- as.POSIXct(seq(from = 1438367408, to = 1440959383, by = 30), origin = "1970-01-01")
dframe <- data.frame(timestamp=t2, power=rnorm(length(t2)))
#using xts
x <- xts(dframe$power,dframe$timestamp)
h1 <- period.apply(x, endpoints(x, "hours"), mean)
h1 <- data.frame(timestamp=trunc(index(h1),'hours'), power=coredata(h1))
#using data.table
h2 <- setDT(dframe)[, list(power= mean(power)) ,(timestamp= as.POSIXct(cut(timestamp, 'hours')))]
#using dpylr
h3 <- dframe %>% group_by(timestamp= as.POSIXct(cut(timestamp, 'hour'))) %>% summarise(power=mean(power))
关于大小的输出:
> dim(h1)
[1] 721 2
> dim(h2)
[1] 720 2
> dim(h3)
[1] 720 2
关于每小时的输出意味着:
> head(h1)
timestamp power
1 2015-08-01 00:00:00 0.04485894
2 2015-08-01 01:00:00 -0.02299071
> head(h2) # equals to head(h2)
timestamp power
1: 2015-08-01 00:00:00 0.10057538
2: 2015-08-01 01:00:00 -0.07456292
h1 的额外观察:
> tail(h1)
timestamp power
719 2015-08-30 22:00:00 0.069544538
720 2015-08-30 23:00:00 0.011673835
721 2015-08-30 23:00:00 -0.053858563
很明显,一天的最后一个小时有两次观察。正常应该只有一个。
我的系统信息:
> sessionInfo()
R version 3.2.2 (2015-08-14)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.10.3 (Yosemite)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] dplyr_0.4.3 data.table_1.9.7 xts_0.9-7 zoo_1.7-12
loaded via a namespace (and not attached):
[1] lazyeval_0.1.10 magrittr_1.5 R6_2.1.1 assertthat_0.1 parallel_3.2.2 DBI_0.3.1 tools_3.2.2
[8] Rcpp_0.12.1 grid_3.2.2 chron_2.3-47 lattice_0.20-33
注:
- 原始数据集可在 link
- 我想要一个解决这个问题的方法,因为在我的实现场景中,xts 比剩下的两个快 35 倍
这看起来可能是 endpoints
中的错误,因为您的本地时区与 UTC 的时差不是整小时。如果我将本地时区设置为您的时区,我可以重现该问题。
R> Sys.setenv(TZ="Asia/Kolkata")
R> x <- xts(dframe$power,dframe$timestamp)
R> h <- period.apply(x, endpoints(x, "hours"), mean)
R> head(h)
[,1]
2015-08-01 00:29:31 124.9055
2015-08-01 01:29:31 129.7197
2015-08-01 02:29:31 139.0899
2015-08-01 03:29:32 145.6592
2015-08-01 04:29:32 153.6840
2015-08-01 05:29:32 114.4809
请注意,端点以半小时为增量,而不是在一小时结束时。这是因为 Asia/Kolkata 是 UTC+0530,而 endpoints
会根据以 UTC 表示的时间进行所有计算。
您可以通过将 POSIXct 对象的时区显式设置为 UTC 来避免这种情况。
require(xts)
require(dplyr)
require(data.table)
Sys.setenv(TZ="Asia/Kolkata")
dframe <- read.csv("~/ap601.csv",head=TRUE,sep=",")
# set timezone on POSIXct object
dframe$timestamp <- as.POSIXct(dframe$timestamp, tz="UTC")
#using xts
x <- xts(dframe$power, dframe$timestamp)
h <- period.apply(x, endpoints(x, "hours"), mean)
h1 <- data.frame(timestamp=trunc(index(h),'hours'), power=coredata(h))
# using data.table
h2 <- setDT(dframe)[, list(power= mean(power)) ,(timestamp= cut(timestamp, 'hour'))]
# using dplyr
h3 <- dframe %>% group_by(timestamp= cut(timestamp, 'hour')) %>% summarise(power=mean(power))
all.equal(h1$power, h2$power) # TRUE
all.equal(h1$power, h3$power) # TRUE
这里有一个变通方法,可以在不将 POSIXct 列的时区设置为 UTC 的情况下获得相同的结果。请注意,这可能不适用于夏令时的时区(Asia/Kolkata 不遵守任何 DST)。
基本上,想法是在计算 endpoints
时从当地时间减去半小时,以便基础 UTC 时间与小时对齐。
dframe <- read.csv("~/ap601.csv",head=TRUE,sep=",")
dframe$timestamp <- as.POSIXct(dframe$timestamp)
# subtract half an hour from the index when calculating endpoints
h <- period.apply(x, endpoints(index(x)-3600*0.5, 'hours'), mean)
h1 <- data.frame(timestamp=trunc(index(h),'hours'), power=coredata(h))
all.equal(h1$power, h2$power) # TRUE
all.equal(h1$power, h3$power) # TRUE