如何在R中每n分钟对时间进行分组

时间:2019-06-04 21:46:18

标签: r datetime time-series aggregate

我有一个时间序列很多的数据框:

1   0:03    B   1
2   0:05    A   1
3   0:05    A   1
4   0:05    B   1
5   0:10    A   1
6   0:10    B   1
7   0:14    B   1
8   0:18    A   1
9   0:20    A   1
10  0:23    B   1
11  0:30    A   1

我想将时间序列每6分钟分组一次,并计算A和B的频率:

1   0:06    A   2
2   0:06    B   2
3   0:12    A   1
4   0:12    B   1
5   0:18    A   1
6   0:24    A   1
7   0:24    B   1
8   0:18    A   1
9   0:30    A   1

此外,时间序列的类别是字符。我该怎么办?

2 个答案:

答案 0 :(得分:2)

这是一种将时间转换为POSIXctcut的时间间隔为6分钟,然后是count的方法。

首先,您需要指定数据的年,月,日,小时,分钟和秒。这将有助于将其缩放到更大的数据集。

library(tidyverse)
library(lubridate)

# sample data
d <- data.frame(t = paste0("2019-06-02 ", 
                           c("0:03","0:06","0:09","0:12","0:15",
                             "0:18","0:21","0:24","0:27","0:30"), 
                           ":00"),
                g = c("A","A","B","B","B"))

d$t <- ymd_hms(d$t) # convert to POSIXct with `lubridate::ymd_hms()`

如果选中新日期列的class,您将看到它是“ POSIXct”。

> class(d$t)
[1] "POSIXct" "POSIXt" 

现在数据位于“ POSIXct”中,您可以每隔cut分钟间隔!我们会将这个新的分组因子添加到名为tc的新列中。

d$tc <- cut(d$t, breaks = "6 min")  
d
                     t g                  tc
1  2019-06-02 00:03:00 A 2019-06-02 00:03:00
2  2019-06-02 00:06:00 A 2019-06-02 00:03:00
3  2019-06-02 00:09:00 B 2019-06-02 00:09:00
4  2019-06-02 00:12:00 B 2019-06-02 00:09:00
5  2019-06-02 00:15:00 B 2019-06-02 00:15:00
6  2019-06-02 00:18:00 A 2019-06-02 00:15:00
7  2019-06-02 00:21:00 A 2019-06-02 00:21:00
8  2019-06-02 00:24:00 B 2019-06-02 00:21:00
9  2019-06-02 00:27:00 B 2019-06-02 00:27:00
10 2019-06-02 00:30:00 B 2019-06-02 00:27:00

现在,您可以group_by这个新的间隔(tc)和您的分组列(g),并计算发生的频率。获取组中观察的频率是相当普遍的操作,因此dplyr为此提供了count

count(d, g, tc)
# A tibble: 7 x 3
  g     tc                      n
  <fct> <fct>               <int>
1 A     2019-06-02 00:03:00     2
2 A     2019-06-02 00:15:00     1
3 A     2019-06-02 00:21:00     1
4 B     2019-06-02 00:09:00     2
5 B     2019-06-02 00:15:00     1
6 B     2019-06-02 00:21:00     1
7 B     2019-06-02 00:27:00     2

如果您在控制台中运行?dplyr::count(),则会看到count(d, tc)只是group_by(d, g, tc) %>% summarise(n = n())的包装。

答案 1 :(得分:0)

根据样本数据集,时间序列以一天中的时间给出,即没有日期。

data.table程序包具有ITime类,它是一天中的时间类,存储为一天中的整数秒数。使用data.table,我们可以使用滚动连接将时间映射到6分钟间隔(右封闭间隔)的上限:

library(data.table)

# coerce from character to class ITime
setDT(ts)[, time := as.ITime(time)]

# create sequence of breaks
breaks <- as.ITime(seq(as.ITime("0:00"), as.ITime("23:59:59"), as.ITime("0:06")))

# rolling join and aggregate
ts[, CJ(breaks, group, unique = TRUE)
   ][ts, on = .(group, breaks = time), roll = -Inf, .(x.breaks, group)
     ][, .N, by = .(upper = x.breaks, group)]

返回

      upper group N
1: 00:06:00     B 2
2: 00:06:00     A 2
3: 00:12:00     A 1
4: 00:12:00     B 1
5: 00:18:00     B 1
6: 00:18:00     A 1
7: 00:24:00     A 1
8: 00:24:00     B 1
9: 00:30:00     A 1

附录

如果滚动连接的方向改变了(由roll = +Inf代替了roll = -Inf),我们将得到左闭合间隔

ts[, CJ(breaks, group, unique = TRUE)
   ][ts, on = .(group, breaks = time), roll = +Inf, .(x.breaks, group)
     ][, .N, by = .(lower = x.breaks, group)]

这将显着改变结果:

      lower group N
1: 00:00:00     B 2
2: 00:00:00     A 2
3: 00:06:00     A 1
4: 00:06:00     B 1
5: 00:12:00     B 1
6: 00:18:00     A 2
7: 00:18:00     B 1
8: 00:30:00     A 1

数据

library(data.table)
ts <- fread("
1   0:03    B   1
2   0:05    A   1
3   0:05    A   1
4   0:05    B   1
5   0:10    A   1
6   0:10    B   1
7   0:14    B   1
8   0:18    A   1
9   0:20    A   1
10  0:23    B   1
11  0:30    A   1"
, header = FALSE
, col.names = c("rn", "time", "group", "value"))