2013-03-19 63 views
1

我有一个非常大的数据框,约1000行和10000列,每列是一个ID,每一行代表一个日期。 数据框中的每个单元格都可以作为该日期到该ID的特定问题的累计发生次数。R中的事件检测

简化数据如下:

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未被计数,因为从8增加到9对id2没有异常); 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循环,你可以提出任何智能算法,使我可以做同样的任务,即找到在数据集中的所有不寻常的事件。

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

+0

我不明白你的一个不寻常的事件的定义,并在你的第一个示例数据集中不能挑选出不寻常的事件。换句话说,我不明白你的顶级数据集中的数字是什么,或者他们为什么改变他们的做法。也许澄清一点。 – 2013-03-19 06:16:28

+0

@MarkMiller 感谢您的评论。对于不常见的情况,我的意思是累积数量突然增加。对于id5说,它没有任何不寻常的,因为那里的数字每天增加一个。但在id2和id4中,我说这很不寻常,因为在某些日期,这个数字增加了很多。例如对于id2,2012-01-08突然增加了一倍。 它有助于解释这一点吗? – 2013-03-19 06:30:00

+0

也许上面的例子不够有意义,但考虑到有1000行,这足以让我为每个id生成一个“通常”的情况,并且因为我可以发现“异常”的情况 – 2013-03-19 06:37:50

回答

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内容是真实的,与paste()which()包裹在另一个apply()结果:

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"  "" 
+0

谢谢你的回答。但我可能不清楚我的问题。我已经从foo函数中得到了结果。这里我的问题是我如何总结它,即[6:7,id2]有一个不寻常的事件,所以输出数据应该有这样一行: ** event#id start_date end_date相关事件**; ** 1 id2 6 7 6 **; – 2013-03-19 07:35:39

+0

@KloserCheung好的,我编辑了我的答案。 – Andrie 2013-03-19 09:35:04