Обнаружение события в R

У меня очень большой фрейм данных, около 1000 строк и 10000 столбцов, каждый столбец является идентификатором, а каждая строка представляет дату. И каждая ячейка во фрейме данных может быть представлена ​​как накопленное количество вхождений для конкретной проблемы до этой даты до этого идентификатора.

Упрощенные данные выглядят следующим образом:

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 раз, что-то в этом роде.

Я собираюсь написать программу для обнаружения любых необычных событий и записи идентификатора, даты начала и даты окончания события. например, id2 имеет необычное событие 08 января 2012 г. (10 января 2012 г. не учитывается, поскольку увеличение с 8 до 9 не является ненормальным для id2); У id4 есть два необычных события, одно 03.01.2012, а другое с 07.01.2012 по 09.01.2012.

Выходные данные будут такими:

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, можете ли вы предложить какой-нибудь умный алгоритм, чтобы я мог выполнить ту же задачу, то есть найти все необычные события в наборе данных.

Кроме того, я знаю, что мой подход к использованию накопленного процента не очень хорош, если у вас есть какие-либо другие предложения, я также готов выслушать вас и поучиться у вас. Благодарю вас!


person Kloser Cheung    schedule 19.03.2013    source источник
comment
Я не понимаю вашего определения необычного события и не могу выделить необычные события в вашем первом примере набора данных. Другими словами, я не понимаю, какие числа находятся в вашем основном наборе данных или почему они меняются так, как они. Возможно, уточните это.   -  person Mark Miller    schedule 19.03.2013
comment
@MarkMiller Спасибо за ваш комментарий. под необычным я подразумеваю какой-то внезапный скачок в накопленном числе. скажем, для id5 в этом нет ничего необычного, потому что число там увеличивается на единицу каждый день. Но в id2 и id4 я говорю, что это необычно, потому что в некоторые даты число сильно увеличилось. например для id2 он внезапно удвоился 08 января 2012 г. это поможет объяснить это?   -  person Kloser Cheung    schedule 19.03.2013
comment
Возможно, приведенный выше пример не имеет достаточного смысла, но, учитывая, что есть 1000 строк, мне было бы достаточно сгенерировать обычный случай для каждого идентификатора, и с тех пор я могу обнаружить необычные.   -  person Kloser Cheung    schedule 19.03.2013
comment
Насколько большим должно быть увеличение, чтобы каждая из пяти колонок считалась необычной?   -  person Mark Miller    schedule 19.03.2013
comment
Теперь я использую произвольное число, скажем, 20%, но я думаю, что могу рассчитать более надежное число для каждого идентификатора из данных. Хотя это будет мой следующий шаг.   -  person Kloser Cheung    schedule 19.03.2013


Ответы (1)


Вы можете упростить свой код, преобразовав данные в 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"      "" 
person Andrie    schedule 19.03.2013
comment
Спасибо за ваш ответ. Но я, возможно, сформулировал свой вопрос неясно. Я уже получил результат от функции foo. Мой вопрос заключается в том, как я могу обобщить это, т. Е. [6: 7, id2] имеет необычное событие, поэтому выходные данные должны иметь строку, подобную этой: event# id start_date end_date связанное событие ; 1 ID2 6 7 6; - person Kloser Cheung; 19.03.2013