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")の場合、その日付の初めから5つのid5アイテムが販売されたか、エラーid5が5回発生したことを意味します。

異常なイベントを検出し、イベントのID、開始日、終了日を記録するプログラムを作成します。たとえば、id2には2012-01-08に異常なイベントがあります(id2では8から9への増加は異常ではないため、2012-01-10はカウントされません)。id4には2つの異常なイベントがあります。1つは2012-01-03にあり、もう1つは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

データを に変換し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要素が true であることを確認するには、結果apply()paste()andで別の要素にラップし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 に答える