更快地计算5分钟段内的事件数量?

时间:2013-07-24 21:13:32

标签: r

我有一个矩阵events,其中包含500万个事件的发生次数。这500万个事件中的每一个都有一个“类型”,范围从1到2000.矩阵的一个非常简化的版本如下。 “时间”的单位是自1970年以来的秒数。所有事件都发生在2012年1月1日以后。

>events
      type          times
      1           1352861760
      1           1362377700
      2           1365491820
      2           1368216180
      2           1362088800
      2           1362377700

我正在尝试将自2012年1月1日以来的时间划分为5分钟的存储桶,然后在每个存储桶中填充每个存储类型i中每个事件的数量。我的代码如下。请注意,types是包含1-2000中每种可能类型的向量,by设置为300,因为这是5分钟内的秒数。

for(i in 1:length(types)){
    local <- events[events$type==types[i],c("type", "times")]
    assign(sprintf("a%d", i),table(cut(local$times, breaks=seq(range(events$times)[1],range(events$times)[2], by=300))))
}

这导致变量a1a2000,其中包含每个5分钟存储桶中出现的类型i的出现次数的行向量。

然后我继续找到'a1'和'a2000'之间的所有成对相关性。

有没有办法优化我上面提供的代码块?它运行速度非常慢,但我想不出一种方法可以让它更快。也许有太多的桶和太少的时间。

非常感谢任何见解。

可重复示例:

>head(events)
     type         times
      12           1308575460
      12           1308676680
      12           1308825420
      12           1309152660
      12           1309879140
      25           1309946460

xevents <- xts(events[,"type"],.POSIXct(events[,"times"]))
ep <- endpoints(xevents, "minutes", 5)
counts <- period.apply(xevents, ep, tabulate, nbins=length(types))

>head(counts)
                       1    2    3    4    5   6    7    8    9   10   11  12   13   14
2011-06-20 09:11:00    0    0    0    0    0   0    0    0    0    0    0   1    0   0
2011-06-21 13:18:00    0    0    0    0    0   0    0    0    0    0    0   1    0   0
2011-06-23 06:37:00    0    0    0    0    0   0    0    0    0    0    0   1    0   0
2011-06-27 01:31:00    0    0    0    0    0   0    0    0    0    0    0   1    0   0
2011-07-05 11:19:00    0    0    0    0    0   0    0    0    0    0    0   1    0   0
2011-07-06 06:01:00    0    0    0    0    0   0    0    0    0    0    0   0    0   0

>> ep[1:20]
[1]  0  1  2  3  4  5  6  7  8  9 10 12 20 21 22 23 24 25 26 27

以上是我一直在使用的代码,但问题是它没有增加5分钟:它只是增加了实际事件的发生。

3 个答案:

答案 0 :(得分:3)

我会使用xts包。使用period.applyendpoints函数可以轻松地以非重叠的5分钟间隔运行函数。

# create sample data
library(xts)
set.seed(21)
N <- 1e6
events <- cbind(sample(2000, N, replace=TRUE),
  as.POSIXct("2012-01-01")+sample(1e7,N))
colnames(events) <- c("type","times")
# create xts object
xevents <- xts(events[,"type"], .POSIXct(events[,"times"]))
# find the last row of each non-overlapping 5-minute interval
ep <- endpoints(xevents, "minutes", 5)
# count the number of occurrences of each "type"
counts <- period.apply(xevents, ep, tabulate, nbins=2000)
# set colnames
colnames(counts) <- paste0("a",1:ncol(counts))
# calculate correlation
#cc <- cor(counts)

更新以回应OP的评论/修改:

# Create a sequence of 5-minute steps, from the actual start of the data
m5 <- seq(round(start(xevents),'mins'), end(xevents), by='5 mins')
# Create a sequence of 5-minute steps, from the start of 2012-01-01
m5 <- seq(as.POSIXct("2012-01-01"), end(xevents), by='5 mins')
# merge xevents with empty 5-minute xts object, and
# subtract 1 second, so endpoints are at end of each 5-minute interval
xevents5 <- merge(xevents, xts(,m5-1))
ep5 <- endpoints(xevents5, "minutes", 5)
counts5 <- period.apply(xevents5, ep5, tabulate, nbins=2000)
colnames(counts5) <- paste0("a",1:ncol(counts5))
# align to the beginning of each 5-minute interval, if you want
counts5 <- align.time(counts5,60*5)

答案 1 :(得分:3)

有500万条记录,我可能会使用data.table。你可以这样做:

#  First we make a sequence of the buckets from initial time to at least the end time + 5 minutes
buckets <- seq( from = min( df$times ) , by = 300 , to = max( df$times )+300 )

require( data.table )
DT <- data.table( df )

#  Work out what bucket each time is in
DT[ , list( Bucket = which.max(times <= buckets ) ) , by = "times" ]

#  Aggregate events by type and time bucket
DT[ , list( Count = length( type ) ) , by = list( type, bucket) ]
   type bucket Count
1:    1      1     1
2:    1  31721     1
3:    2  42102     1
4:    2  51183     1
5:    2  30758     1
6:    2  31721     1

答案 2 :(得分:1)

cut它位于range times内,就像你做的那样。之后,您可以使用tablextabs进行制表,但对于整个数据集,可以生成矩阵。如下所示:

r <- trunc(range(events$times) / 300) * 300
events$times.bin <- cut(events$times, seq(r[1], r[2] + 300, by=300))
xtabs(~type+times.bin, events, drop.unused.levels=T)

决定是否要drop.unused.levels。使用此类数据,您可能还需要创建sparse矩阵。