【问题标题】:Convert seconds interval data to hourly mean representation in LESS TIME在 LESS TIME 中将秒间隔数据转换为每小时平均表示
【发布时间】:2015-10-19 05:26:42
【问题描述】:

我有一个数据文件,其中包含持续时间为 30 秒的采样读数。文件组织为:

> head(dframe)
            timestamp    power
1 2015-08-01 00:00:04 584.1379
2 2015-08-01 00:00:34 585.8087
3 2015-08-01 00:01:04 584.9335
4 2015-08-01 00:01:34 584.4366
5 2015-08-01 00:02:04 584.2829

现在将 30 秒的持续时间数据表示为每小时意味着我使用以下 R 命令:

df = aggregate(list(power=dframe$power),by=list(timestamp=cut(as.POSIXct(dframe$timestamp),"hour")),mean) 

这非常有效。但是,实际问题是大文件(一年的数据)所花费的时间。我可以以某种方式减少转换过程所需的时间吗?换句话说,在 R 中,是否有任何其他最佳替代方案可以减少将秒数据转换为每小时平均数据的时间?

更新: 对于@akrun 和@Joshua 建议的相同问题,我使用了4 种不同的方法。对于堆栈溢出的其他用户,我提供了所有方法的用法和相应的时间

dframe<-read.csv(path,head=TRUE,sep=",")
dframe$timestamp<- as.POSIXct(dframe$timestamp)
xframe = dframe
#using aggregate
system.time(
df1<- aggregate(list(power=dframe$power),by=list(timestamp=cut(dframe$timestamp,"hour")),mean)
)
# using data.table
system.time(
dfx<-setDT(dframe)[, list(power= mean(power)) ,(timestamp= cut(timestamp, 'hour'))]
)
# using dplyr
system.time( 
xframe %>% group_by(timestamp= cut(timestamp, 'hour')) %>% summarise(power=mean(power))
)
#using xts
system.time({
  x <- xts(dframe$power,dframe$timestamp)
  h <- period.apply(x, endpoints(x, "hours"), mean)
  h <- data.frame(timestamp=trunc(index(h),'hours'), power=coredata(h))
})

在两个(一个月、三个月)不同的数据集上分别采用的时间是:对于一个月的数据集:

Method       user  system elapsed 
Aggregate    0.137   0.005   0.142
data.table   0.031   0.001   0.032 
dplyr        0.035   0.001   0.036  
xts          0.053   0.000   0.053  

对于三个月的数据集:

Aggregate    0.456   0.019   0.475 
data.table   0.099   0.002   0.102  
dplyr        0.099   0.004   0.103  
xts          0.158   0.004   0.161

警告:除了 xts 之外的所有方法都将时间戳的类型从 POSIXct 更改为 Factor。这意味着您必须再次转换时间戳列的类型,这将导致更多的 CPU 周期。简而言之,如果最终您还需要 POSIXct 时间戳,那么 xts 是最好的,否则请使用 data.table。

数据集可以在link找到使用的数据集

【问题讨论】:

  • 你可以试试dplyr, library(dplyr); dframe %&gt;% group_by(timestamp= cut(as.POSIXct(timestamp), 'hour') %&gt;% summarise(power=mean(power))
  • 我猜 cut 导致了很多减速
  • @akrun。谢谢。 data.table 比我使用的所有选项花费的时间更少。请提供您的第一个(使用 data.table)评论作为答案。同时,我将在主要问题中添加统计数据。我仍然很困惑为什么它在早上给出了不好的结果!

标签: r time-series


【解决方案1】:

使用 xts 包中的工具,您可以在不到一半的时间内完成此聚合。

# sample data
set.seed(21)
N <- 2e6
dframe <- data.frame(timestamp=seq(Sys.time(), by="30 sec", length.out=N),
                     power=rnorm(N))
# aggregate
system.time(a <- aggregate(list(power=dframe$power),by=list(timestamp=cut(dframe$timestamp,"hour")), mean))
#    user  system elapsed 
#   2.456   0.000   2.457 

# xts
system.time({
  x <- xts(dframe$power, dframe$timestamp)
  h <- period.apply(x, endpoints(x, "hours"), mean)
  h <- data.frame(timestamp=trunc(index(h),'hours'), power=coredata(h))
})
#    user  system elapsed 
#   0.888   0.004   0.893 

【讨论】:

  • 我使用了 xts 并比较了其他方法。它的输出并不令人印象深刻。似乎 data.table 花费的时间非常少。我已在主要问题中提供了所有结果作为更新
  • Xts 的行为方式很奇怪。每当我使用 xts 包时,它会产生 721 个观察结果,而上述三种方法的其余部分会产生 720 个观察结果。 xts 提供的每小时方式也与其他方法略有不同。为了澄清起见,我也包含了有问题的数据集。
  • @HaroonRashid:这可能是时区问题。您应该可以通过在POSIXct 列上设置时区来解决它(例如attr(dframe$timestamp, 'tzone') &lt;- "UTC"
  • 我使用了attr(dframe$timestamp, "tzone") &lt;- "Asia/Kolkata",但仍然没有效果。我的时间戳列设置正确,因为head(dframe$timestamp[1]) is "2015-08-01 00:00:04 IST" 的输出。这是真的。
  • 我怀疑 period.apply 函数。我在 xts() 中发现了一件有趣的事情。每当我使用 xts 转换数据时,输出时间戳列始终采用 POSIXct 形式,而在其余方法中,它会转换为因子形式。
【解决方案2】:

一般来说,aggregate 很慢。我们可以使用data.table 来加快速度。将'data.frame'转换为'data.table'(setDT(dframe)),我们使用cut从'timestamp'创建一个分组变量,得到'power'的mean

library(data.table)
setDT(dframe)[, list(power= mean(power)) ,(timestamp= cut(as.POSIXct(timestamp), 'hour'))]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 1970-01-01
    • 2019-11-06
    • 2021-02-16
    • 1970-01-01
    • 2021-04-05
    相关资源
    最近更新 更多