3

我有一个 CSV 文件,其中包含此时发生的时间戳和某些事件类型。我想要的是每隔 6 分钟计算某些事件类型的发生次数。

输入数据如下所示:

date,type
"Sep 22, 2011 12:54:53.081240000","2"
"Sep 22, 2011 12:54:53.083493000","2"
"Sep 22, 2011 12:54:53.084025000","2"
"Sep 22, 2011 12:54:53.086493000","2"

我用这段代码加载和处理数据:

> raw_data <- read.csv('input.csv')
> cured_dates <- c(strptime(raw_data$date, '%b %d, %Y %H:%M:%S', tz="CEST"))
> cured_data <- data.frame(cured_dates, c(raw_data$type))
> colnames(cured_data) <- c('date', 'type')

固化后的数据如下所示:

> head(cured_data)
                 date type
1 2011-09-22 14:54:53    2
2 2011-09-22 14:54:53    2
3 2011-09-22 14:54:53    2
4 2011-09-22 14:54:53    2
5 2011-09-22 14:54:53    1
6 2011-09-22 14:54:53    1

我为 xts 和 zoo 阅读了很多样本​​,但不知何故我无法掌握它。输出数据应类似于:

date                       type   count
2011-09-22 14:54:00 CEST   1      11
2011-09-22 14:54:00 CEST   2      19
2011-09-22 15:00:00 CEST   1      9
2011-09-22 15:00:00 CEST   2      12
2011-09-22 15:06:00 CEST   1      23
2011-09-22 15:06:00 CEST   2      18

Zoo 的聚合函数看起来很有希望,我发现了这个代码片段:

# aggregate POSIXct seconds data every 10 minutes
tt <- seq(10, 2000, 10)
x <- zoo(tt, structure(tt, class = c("POSIXt", "POSIXct")))
aggregate(x, time(x) - as.numeric(time(x)) %% 600, mean)

现在我只是想知道如何将其应用于我的用例。

我尝试过天真:

> zoo_data <- zoo(cured_data$type, structure(cured_data$time, class = c("POSIXt", "POSIXct")))
> aggr_data = aggregate(zoo_data$type, time(zoo_data$time), - as.numeric(time(zoo_data$time)) %% 360, count)
Error in `$.zoo`(zoo_data, type) : not possible for univariate zoo series

我必须承认我对 R 不是很有信心,但我会尝试。:-)

我有点迷路了。谁能指出我正确的方向?

非常感谢!干杯,亚历克斯。

这里是我数据的一小部分的 dput 输出。数据本身大约有 8000 万行。

structure(list(date = structure(c(1316697885, 1316697885, 1316697885, 
1316697885, 1316697885, 1316697885, 1316697885, 1316697885, 1316697885, 
1316697885, 1316697885, 1316697885, 1316697885, 1316697885, 1316697885, 
1316697885, 1316697885, 1316697885, 1316697885, 1316697885, 1316697885, 
1316697885, 1316697885), class = c("POSIXct", "POSIXt"), tzone = ""), 
    type = c(2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 
    1L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 2L)), .Names = c("date", 
"type"), row.names = c(NA, -23L), class = "data.frame")
4

2 回答 2

3

我们可以使用 读取它read.csv,将第一列转换为以 6 分钟为间隔的日期时间,并添加一个 1 的虚拟列。read.zoo然后使用拆分类型并聚合虚拟列重新读取它:

# test data

Lines <- 'date,type
"Sep 22, 2011 12:54:53.081240000","2"
"Sep 22, 2011 12:54:53.083493000","2"
"Sep 22, 2011 12:54:53.084025000","2"
"Sep 22, 2011 12:54:53.086493000","2"
"Sep 22, 2011 12:54:53.081240000","3"
"Sep 22, 2011 12:54:53.083493000","3"
"Sep 22, 2011 12:54:53.084025000","3"
"Sep 22, 2011 12:54:53.086493000","4"'

library(zoo)
library(chron)

# convert to chron and bin into 6 minute bins using trunc
# Also add a dummy column of 1's 
# and remove any leading space (removing space not needed if there is none)

DF <- read.csv(textConnection(Lines), as.is = TRUE)
fmt <- '%b %d, %Y %H:%M:%S'
DF <- transform(DF, dummy = 1,
         date = trunc(as.chron(sub("^ *", "", date), format = fmt), "00:06:00"))

# split and aggregate

z <- read.zoo(DF, split = 2, aggregate = length)

使用上述测试数据,解决方案如下所示:

> z
                    2 3 4
(09/22/11 12:54:00) 4 3 1

请注意,上述内容是以宽形式完成的,因为该形式构成时间序列,而长形式则不。每种类型都有一列。在我们的测试数据中,我们有类型 2、3 和 4,所以一共有三列。

(我们在这里使用了 chron ,因为它的trunc方法非常适合分箱为 6 分钟组。chron 不支持时区,这可能是一个优势,因为您无法做出许多可能的时区错误之一,但如果您想要 POSIXct 无论如何转换最后,例如time(z) <- as.POSIXct(paste(as.Date.dates(time(z)), times(time(z)) %% 1))。这个表达式显示在 R News 4/1 文章之一的表格中,除了我们使用as.Date.dates而不是仅仅as.Date解决似乎从那时起引入的错误。我们也可以使用time(z) <- as.POSIXct(time(z))但是将导致不同的时区。)

编辑:

最初的解决方案分为日期,但后来我注意到您希望将其分为 6 分钟的时间段,因此修改了解决方案。

编辑:

根据评论修改。

于 2011-09-23T14:27:29.300 回答
2

你几乎一直在那里。您现在需要做的就是创建该数据的 zoo-isch 版本并将其映射到 aggregate.zoo 代码。由于您想同时按时间和类型进行分类,因此您对 aggregate.zoo 的第二个参数必须更复杂一些,并且您需要计数而不是平均值,因此您应该使用 length()。我不认为这count是一个基本的 R 或 zoo 函数,count我在工作区中看到的唯一函数来自 pkg:plyr,所以我不知道它与 aggregate.zoo 的关系如何。length像大多数人对向量的期望一样工作,但在使用 data.frames 时常常让人们感到惊讶。如果你没有得到你想要的length,那么你应该看看是否NROW代替工作(并且使用您的数据布局,它们都成功):对于新的数据对象,必须首先放置类型参数。并且它发现聚合/动物园只处理单个类别分类器,因此您需要放入 as.vector 以删除它的动物园性:

with(cured_data, 
     aggregate(as.vector(x), list(type = type, 
                                   interval=as.factor(time(x) - as.numeric(time(x)) %% 360)),
                             FUN=NROW) 
 )

#  interval            x 
#1 2011-09-22 09:24:00 12
#2 2011-09-22 09:24:00 11

这是从您获得代码的位置修改的示例(WizaRd Dirk 的 SO 示例): 在任意时间范围内聚合(计数)值的出现

tt <- seq(10, 2000, 10)
x <- zoo(tt, structure(tt, class = c("POSIXt", "POSIXct")))
aggregate(as.vector(x), by=list(cat=as.factor(x), 
     tms = as.factor(index(x) - as.numeric(index(x)) %% 600)), length)

   cat                 tms  x
1    1 1969-12-31 19:00:00 26
2    2 1969-12-31 19:00:00 22
3    3 1969-12-31 19:00:00 11
4    1 1969-12-31 19:10:00 17
5    2 1969-12-31 19:10:00 28
6    3 1969-12-31 19:10:00 15
7    1 1969-12-31 19:20:00 17
8    2 1969-12-31 19:20:00 16
9    3 1969-12-31 19:20:00 27
10   1 1969-12-31 19:30:00  8
11   2 1969-12-31 19:30:00  4
12   3 1969-12-31 19:30:00  9
于 2011-09-23T13:26:06.643 回答