在任意时间范围内聚合(计数)值的出现次数

时间:2011-09-23 11:56:02

标签: r xts zoo

我有一个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和动物园阅读了很多样本​​,但不知怎的,我无法抓住它。 输出数据应如下所示:

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没有信心,但我试试。 : - )

我有点失落。有人能指出我正确的方向吗?

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

这里是我的一小部分数据的输出输出。数据本身大约有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")

2 个答案:

答案 0 :(得分: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 1}}解决从那时起似乎已经引入的错误。我们也可以使用time(z) <- as.POSIXct(time(z))但这会导致不同的时区。)

编辑:

原始解决方案已合并到日期中,但之后我注意到您希望将其分成6分钟,以便修改解决方案。

编辑:

根据评论进行修订。

答案 1 :(得分:2)

你几乎一直都在那里。您现在需要做的就是创建该数据的zoo-isch版本并将其映射到aggregate.zoo代码。既然你想要按时间和类型分类你的第二个参数到aggregate.zoo必须有点复杂,你需要计数而不是手段所以你应该使用length()。我认为count不是基本的R或动物园函数,我在工作空间中看到的唯一count函数来自pkg:plyr所以我不知道它对聚合有多好。动物园。 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示例): Aggregate (count) occurences of values over arbitrary timeframe

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