检测R中的事件

时间:2013-03-19 04:38:51

标签: r detection

我有一个非常大的数据框,大约有1000行和10000列,每列都是一个ID,每一行代表一个日期。 并且数据框中的每个单元格都可以作为截至该ID的特定问题的累计出现次数。

简化数据如下:

Date       id1 id2 id3 id4 id5
2012-01-01   0   1   0   2   1
2012-01-02   0   2   0   2   2
2012-01-03   2   2   0   8   3
2012-01-04   2   2   1   8   4
2012-01-05   2   2   1   8   5
2012-01-06   4   3   1   8   6
2012-01-07   4   5   1  14   7
2012-01-08   5   8   1  16   8
2012-01-09   5   8   1  20   9
2012-01-10   5   9   1  20  10

因此,对于单元格(“2012-01-05”,“id5”),它可能意味着从开始到该日期,出售了5项id5,或者错误id5已经发生了5次,类似于这一点。

我打算编写一个程序来检测任何异常事件并记录事件的id,开始日期和结束日期。 例如,id2在2012-01-08有一个不寻常的事件(2012-01-10不算,因为id2从8增加到9没有异常); id4有两个不寻常的事件,一个是2012-01-03,另一个是2012-01-07到2012-01-09

输出数据如下:

Event IDs Start_Date    End_Date  number_Unusual
    1 id2 2012-01-08  2012-01-08               5
    2 id4 2012-01-03  2012-01-03               6
    2 id4 2012-01-07  2012-01-09              12
    ....

number_Unusual:它是异常时间范围内出现的次数。

我使用以下方法: 1.计算累计百分比变化:

Date    id1 id2 id3 id4 id5
1/1/2012    0.00    0.11    0.00    0.10    0.10
1/2/2012    0.00    0.22    0.00    0.10    0.20
1/3/2012    0.40    0.22    0.00    0.40    0.30
1/4/2012    0.40    0.22    1.00    0.40    0.40
1/5/2012    0.40    0.22    1.00    0.40    0.50
1/6/2012    0.80    0.33    1.00    0.40    0.60
1/7/2012    0.80    0.56    1.00    0.70    0.70
1/8/2012    1.00    0.89    1.00    0.80    0.80
1/9/2012    1.00    0.89    1.00    1.00    0.90
1/10/2012   1.00    1.00    1.00    1.00    1.00

2。找出固定时间范围的差异,比如3天差异:

Date    id1 id2 id3 id4 id5
1/4/2012    0.40    0.11    1.00    0.30    0.30
1/5/2012    0.40    0.00    1.00    0.30    0.30
1/6/2012    0.40    0.11    1.00    0.00    0.30
1/7/2012    0.40    0.33    0.00    0.30    0.30
1/8/2012    0.60    0.67    0.00    0.40    0.30
1/9/2012    0.20    0.56    0.00    0.60    0.30
1/10/2012   0.20    0.44    0.00    0.30    0.30

3。到目前为止,我已到达这里,下一步我将找出任何不寻常的大值,以便有可能发生异常事件。我知道我可以使用一些for循环来完成我的任务,例如,对于id2,我知道它的增量大于0.2并不常见,所以:

event <- c(0)
ids   <- c(0)
start <- c("")
end   <- c("")
for (id in c(id1:id5))
  for (date in 2012-01-04:2012-01-10)
    if value[date, id] > 0.2
      event <- event + 1 
      ids[event] <- id
      start[event] <- date
      end[event]   <- 2012-01-10
      for (date2 in date:2012-01-10)
         if value[date2, id] <= 0.2 {
            end[event]   <- date2
            skip
         }

很抱歉,如果上面的伪代码有任何错误,我只是想表达我的想法。

现在我的问题是,您可以建议任何智能算法,而不是使用这个愚蠢的for循环,以便我可以执行相同的任务,即查找数据集中的所有异常事件。

而且,我知道我使用累积百分比的方法不是一个很好的方法,如果你有任何其他建议,我也愿意倾听并向你学习。 谢谢!

1 个答案:

答案 0 :(得分:2)

您可以将数据转换为matrix,然后使用apply()获取正在运行的分数,diff()来计算差异,从而简化代码。

重新创建数据:

x <- read.table(tex='
Date       id1 id2 id3 id4 id5
2012-01-01   0   1   0   2   1
2012-01-02   0   2   0   2   2
2012-01-03   2   2   0   8   3
2012-01-04   2   2   1   8   4
2012-01-05   2   2   1   8   5
2012-01-06   4   3   1   8   6
2012-01-07   4   5   1  14   7
2012-01-08   5   8   1  16   8
2012-01-09   5   8   1  20   9
2012-01-10   5   9   1  20  10
', header=TRUE)

然后设置一个函数来进行差分:

foo <- function(x, periods=3, exception=0.1){
  xm <- as.matrix(x)
  xp <- apply(xm, 2, function(z)z/tail(z, 1))
  diff2 <- diff(diff(xp, periods), 1)
  NAs <- matrix(NA, ncol=ncol(x), nrow=3)
  rbind(NAs, abs(diff2) > exception)
}

你得到:

foo(x[, -1], periods=3, exception=0.2)

        id1   id2   id3   id4   id5
 [1,]    NA    NA    NA    NA    NA
 [2,]    NA    NA    NA    NA    NA
 [3,]    NA    NA    NA    NA    NA
 [4,] FALSE FALSE FALSE FALSE FALSE
 [5,] FALSE FALSE FALSE  TRUE FALSE
 [6,] FALSE  TRUE  TRUE  TRUE FALSE
 [7,] FALSE  TRUE FALSE FALSE FALSE
 [8,]  TRUE FALSE FALSE FALSE FALSE
 [9,] FALSE FALSE FALSE  TRUE FALSE

修改

要找出which元素为真,请将结果用apply()paste()包裹在另一个which()中:

z <- foo(x[, -1], periods=3, exception=0.2)
apply(z, 2, function(x)paste(which(x), collapse="_"))

    id1     id2     id3     id4     id5 
    "8"   "6_7"     "6" "5_6_9"      ""