【问题标题】:Aggregate (count) occurences of values over arbitrary timeframe在任意时间范围内聚合(计数)值的出现
【发布时间】:2011-09-23 11:56:01
【问题描述】:

我有一个 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 的聚合函数看起来很有希望,我找到了这个 code-sn-p:

# 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")

【问题讨论】:

  • 首先,感谢到目前为止的所有回复!我现在将仔细阅读您提供的不同提示,并让您知道我能走多远。

标签: r xts zoo


【解决方案1】:

我们可以使用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) &lt;- as.POSIXct(paste(as.Date.dates(time(z)), times(time(z)) %% 1)) 。此表达式显示在 R News 4/1 文章之一的表格中,除了我们使用 as.Date.dates 而不是仅使用 as.Date 来解决错误这似乎是从那时起引入的。我们也可以使用time(z) &lt;- as.POSIXct(time(z)),但这会导致不同的时区。)

编辑:

最初的解决方案是按日期分档的,但后来我注意到您希望分档为 6 分钟,因此修改了解决方案。

编辑:

根据评论修改。

【讨论】:

  • cbind() 中的 read.ag(mean) 有点令人困惑;我在更多数据上运行它,现在还有 type=1 的数据行,我最终得到 gist.github.com/d779b0546765b7640804 。我真的不想聚合平均值,但想在 SQL 中使用更多类似 COUNT() 的东西来处理不同的类型值(类型可以是 1 到 5 之间的任何整数)。
【解决方案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 示例): 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

【讨论】:

  • 嘿,到目前为止看起来还不错,但它只显示了 type=1 的聚合数据:gist.github.com/8049f54780cf0f18147b Hmmmmm!我会进一步研究。
  • 更好地展示您的数据,您将获得更快、更好、经过测试的答案。看函数dput
  • 抱歉不够精确,感谢您的努力。我将 dput 的输出添加到我的原始帖子中。
  • 所有这些“日期”都是相同的。我以为你想要某种级数计算?而且我相信你的话,聚合代码可以按照你的意愿工作,但你从来没有提到它的来源。
  • 是的,仅在本系列的这一部分中。整个时间范围约为 45 分钟(它是来自 ISP 的登录/注销统计信息),每秒大约有 200-400 行,其中 type=1(RADIUS 记帐请求开始)或 type=2(RADIUS 记帐请求停止)。我想知道每 6 分钟时间范围内有多少次开始/停止。原始数据具有微秒精度的时间。
猜你喜欢
  • 2012-09-18
  • 1970-01-01
  • 2021-07-17
  • 2012-01-27
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 2017-05-21
  • 1970-01-01
相关资源
最近更新 更多