1

我有一个非常大的数据框,大约有 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”),这可能意味着从开始到该日期,id5 已售出 5 件商品,或者错误 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 循环之外,您能否建议任何智能算法,以便我可以完成相同的任务,即在数据集中找到所有不寻常的事件。

另外,我知道我使用累积百分比的方法不是很好,如果您有其他建议,我也愿意倾听和学习。谢谢!

4

1 回答 1

2

您可以通过将数据转换为 a 来简化代码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

编辑

要找出元素是否为真,请使用andwhich将结果包装在另一个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"      "" 
于 2013-03-19T07:20:28.097 回答