【问题标题】:Create a time interval of 15 minutes from minutely data in R?从 R 中的每分钟数据创建 15 分钟的时间间隔?
【发布时间】:2016-08-18 01:50:25
【问题描述】:

我有一些按以下方式格式化的数据:

time     count 
00:00    17
00:01    62
00:02    41

所以我有从 00:00 到 23:59 的时间,每分钟有一个计数器。我想以 15 分钟为间隔对数据进行分组:

time           count
00:00-00:15    148   
00:16-00:30    284

我尝试过手动操作,但这很累,所以我确信必须有一个函数或某事才能轻松完成,但我还没有弄清楚如何去做。

我真的很感激一些帮助!

非常感谢!

【问题讨论】:

  • 您是如何将数据转换为 POSIXct 的?我有更多相同的数据,但无法正确转换它们。我得到NAs

标签: r time format


【解决方案1】:

对于 POSIXct 格式的数据,您可以使用 cut 函数创建 15 分钟分组,然后按这些组聚合。下面的代码展示了如何在 base R 以及 dplyrdata.table 包中执行此操作。

首先,创建一些假数据:

set.seed(4984)
dat = data.frame(time=seq(as.POSIXct("2016-05-01"), as.POSIXct("2016-05-01") + 60*99, by=60),
                 count=sample(1:50, 100, replace=TRUE))

基础 R

cut将数据分成15分钟组:

dat$by15 = cut(dat$time, breaks="15 min")
                   time count                by15
1   2016-05-01 00:00:00    22 2016-05-01 00:00:00
2   2016-05-01 00:01:00    11 2016-05-01 00:00:00
3   2016-05-01 00:02:00    31 2016-05-01 00:00:00
...
98  2016-05-01 01:37:00    20 2016-05-01 01:30:00
99  2016-05-01 01:38:00    29 2016-05-01 01:30:00
100 2016-05-01 01:39:00    37 2016-05-01 01:30:00

现在aggregate被新的分组列,使用sum作为聚合函数:

dat.summary = aggregate(count ~ by15, FUN=sum, data=dat)
                 by15 count
1 2016-05-01 00:00:00   312
2 2016-05-01 00:15:00   395
3 2016-05-01 00:30:00   341
4 2016-05-01 00:45:00   318
5 2016-05-01 01:00:00   349
6 2016-05-01 01:15:00   397
7 2016-05-01 01:30:00   341

dplyr

library(dplyr)

dat.summary = dat %>% group_by(by15=cut(time, "15 min")) %>%
  summarise(count=sum(count))

data.table

library(data.table)

dat.summary = setDT(dat)[ , list(count=sum(count)), by=cut(time, "15 min")]

更新:回答评论,对于这种情况,每个分组间隔的终点是as.POSIXct(as.character(dat$by15)) + 60*15 - 1。换句话说,分组间隔的终点是从间隔开始算起的 15 分钟减去 1 秒。我们添加 60*15 - 1 因为POSIXct 以秒为单位。 as.POSIXct(as.character(...)) 是因为 cut 返回一个因子,这只是将其转换回日期时间,以便我们可以对其进行数学运算。

如果您希望终点指向下一个间隔之前的最近一分钟(而不是最近的一秒),您可以发送至as.POSIXct(as.character(dat$by15)) + 60*14

如果您不知道中断间隔,例如,因为您选择了中断次数并让 R 选择间隔,您可以通过执行 max(unique(diff(as.POSIXct(as.character(dat$by15))))) - 1 找到要添加的秒数。

【讨论】:

  • 这是一个很好的答案!您如何(最)有效地找到每个间隔的端点?
  • 完美答案!非常感谢!
  • 你说的是For data that is in POSIXct format do... 但问题不在于POSIXct 格式。您是如何将数据更改为该格式的?
  • as.POSIXct 在基础 R 中(如答案中所述)或 mdy_hmsymd_hms 等之一与 lubridate 包。
  • 你的数据看起来像这样2018-01-02 03:04:00"吗?还是这个"03:04:00"?还是其他格式?如果您提供有关您遇到的问题的更多信息,将会更容易为您提供帮助。
【解决方案2】:

cut 方法很方便,但对于大型数据帧来说速度很慢。以下方法比切割方法快大约 1,000 倍(使用 400k 记录进行测试。)

  #     Function: Truncate (floor) POSIXct to time interval (specified in seconds)
  #       Author: Stephen McDaniel @ PowerTrip Analytics
  #        Date : 2017MAY
  #    Copyright: (C) 2017 by Freakalytics, LLC
  #      License: MIT

  floor_datetime <- function(date_var, floor_seconds = 60, 
        origin = "1970-01-01") { # defaults to minute rounding
     if(!is(date_var, "POSIXct")) stop("Please pass in a POSIXct variable")
     if(is.na(date_var)) return(as.POSIXct(NA)) else {
        return(as.POSIXct(floor(as.numeric(date_var) / 
           (floor_seconds))*(floor_seconds), origin = origin))
     }
  }

示例输出:

test <- data.frame(good = as.POSIXct(Sys.time()), 
   bad1 = as.Date(Sys.time()),
   bad2 = as.POSIXct(NA))

test$good_15 <- floor_datetime(test$good, 15 * 60)
test$bad1_15 <- floor_datetime(test$bad1, 15 * 60)
Error in floor_datetime(test$bad, 15 * 60) : 
  Please pass in a POSIXct variable
test$bad2_15 <- floor_datetime(test$bad2, 15 * 60)

test

                        good       bad1 bad2             good_15 bad2_15
    1 2017-05-06 13:55:34.48 2017-05-06 <NA> 2007-05-06 13:45:00    <NA>

【讨论】:

  • 500k 对我来说快 5-10 倍。仍然是一个改进谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 2017-10-31
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多