R - Анализ раздвижных дверей Количество событий за период времени

Я повторяю этот вопрос, так как думал, что мне нужен анализ кластерного типа, но требуется скорее анализ «скользящего окна». У меня есть набор данных с 59 тыс. записей, записанных за 63 года, мне нужно определить «кластеры» событий с такими критериями:

Последовательность из 6 или более событий с интервалом не более 6 часов между последовательными событиями в последовательности.

Каждое событие имеет уникальный идентификатор и отметку даты/времени. Выходные данные в идеале присваивают идентификатор кластера событиям, которые соответствуют указанным выше критериям. Я был направлен на подход с раздвижным окном, лучший вариант для использования? может быть, используя rollapply из пакета зоопарка?

Я добавил образец данных за один год, если кто-то чувствует себя очень полезным. https://dl.dropboxusercontent.com/u/16400709/StackOverflow/DataStack.csv

Я видел результат такого анализа в R, но пока не смог воспроизвести его, результаты этого анализа можно увидеть в этой статье --> https://dl.dropboxusercontent.com/u/16400709/StackOverflow/fuhrmann_etal_waf2014.pdf

Спасибо за ваше время!


person Methexis    schedule 05.08.2014    source источник


Ответы (1)


Вот решение с использованием rollapply из пакета zoo.

require(chron)
require(zoo)

d <- read.csv("path/to/file/DataStack.csv")
d[] <- lapply(d, as.character)

d$time <- chron(d$Date, d$Time, format = c(dates = "d/m/y", times = "h:m:s"))
d <- d[order(d$time), ]
d$diffHours <- c(0, diff(d$time)) * 24
d$withinSixHr <- ifelse(d$diffHours < 6, 1, 0)
d$streak <- c(rep(NA, 5), rollapply(zoo(d$withinSixHr), width = 6, FUN = sum))
d$cluster <- ifelse(d$streak == 6, 1, 0)

d$clusterParticipant <- 0

for (i in 6:nrow(d)) {

  if (d[i, "cluster"] == 1) {

    d[i - 5, "clusterParticipant"] <- 1
    d[i - 4, "clusterParticipant"] <- 1
    d[i - 3, "clusterParticipant"] <- 1
    d[i - 2, "clusterParticipant"] <- 1
    d[i - 1, "clusterParticipant"] <- 1
    d[i - 0, "clusterParticipant"] <- 1

  }
}

И вот результат:

> head(d[c(1, 5:10)], n = 20)
   EventID                time   diffHours withinSixHr streak cluster clusterParticipant
2   272481 (01/01/11 00:02:00)   0.0000000           1     NA      NA                  1
3   272666 (01/01/11 00:40:00)   0.6333333           1     NA      NA                  1
4   272674 (01/01/11 00:46:00)   0.1000000           1     NA      NA                  1
5   272701 (01/01/11 01:15:00)   0.4833333           1     NA      NA                  1
6   272715 (01/01/11 02:00:00)   0.7500000           1     NA      NA                  1
7   272720 (01/01/11 02:25:00)   0.4166667           1      6       1                  1
8   272723 (01/01/11 02:56:00)   0.5166667           1      6       1                  1
21  278829 (09/01/11 03:25:00) 192.4833333           0      5       0                  0
1   268346 (17/01/11 10:03:00) 198.6333333           0      4       0                  0
43  280736 (25/01/11 15:35:00) 197.5333333           0      3       0                  0
26  279417 (25/01/11 17:15:00)   1.6666667           1      3       0                  1
44  280739 (25/01/11 17:41:00)   0.4333333           1      3       0                  1
45  280740 (25/01/11 18:08:00)   0.4500000           1      3       0                  1
46  280751 (25/01/11 18:40:00)   0.5333333           1      4       0                  1
47  280806 (25/01/11 19:09:00)   0.4833333           1      5       0                  1
48  281559 (25/01/11 21:50:00)   2.6833333           1      6       1                  1
14  276331 (01/02/11 06:10:00) 152.3333333           0      5       0                  0
15  276336 (01/02/11 08:24:00)   2.2333333           1      5       0                  0
50  281741 (01/02/11 20:06:00)  11.7000000           0      4       0                  0
11  275388 (24/02/11 15:53:00) 547.7833333           0      3       0                  0

РЕДАКТИРОВАТЬ: приведенный ниже код предназначен для присвоения каждому кластеру (или суперкластеру) идентификационного номера. Он создает переменную clusterDiff и использует ее в качестве коммутатора, чтобы определить, изменилось ли состояние кластера. Это будет довольно медленно на большом наборе данных, но сработает.

d$clusterDiff <- c(d[1, "clusterParticipant"], diff(d$clusterParticipant))
d$clusterID <- as.numeric(NA)

count <- 1
inCluster <- FALSE

for (i in 1:nrow(d)) {

  if (d[i, "clusterDiff"] == 1) { 
    d[i, "clusterID"] <- count
    inCluster <- TRUE 

  } else if (d[i, "clusterDiff"] == -1) { 
    inCluster <- FALSE
    count <- count + 1

  } else if (inCluster == TRUE & d[i, "clusterDiff"] == 0) {
    d[i, "clusterID"] <- count

  } else { next }

}
person rsoren    schedule 05.08.2014
comment
Выглядит здорово, просто собираюсь просмотреть полный набор данных и посмотреть, как у нас дела. Приведенные выше результаты выглядят многообещающе! - person Methexis; 06.08.2014
comment
Здравствуйте, я попробовал запустить код, пару быстрых вопросов, почему у вас есть «d []», почему бы вам просто не назвать его «d», никогда раньше этого не видел, при установке данных в d [] I получить ошибку «количество заменяемых элементов не кратно длине замены». Также d ‹- d[order(d$time), ] выдает ошибку «неправильное количество измерений». Если я применю только к d и не буду заказывать, то я могу получить результаты до d$cluster, но команда head() не печатает так, как указано выше! Надеюсь, это имеет смысл?! - person Methexis; 06.08.2014
comment
Я внес изменение, которое должно правильно считывать данные для вас и должно позаботиться об ошибках, о которых вы упомянули. Просто измените путь к файлу, где вы храните DataStack.csv. Я использую d[], чтобы сохранить структуру фрейма данных d, иначе результатом lapply будет список. - person rsoren; 06.08.2014
comment
Рид еще раз спасибо, попробую еще раз. Я узнал больше из stackoverflow, чем из любой книги или онлайн-урока! - person Methexis; 06.08.2014
comment
Я узнал об этом из превосходной (бесплатной) онлайн-книги Хэдли Уикхема Advanced R (adv-r.had .co.nz). Настоятельно рекомендуется, если у вас есть время поработать над этим. - person rsoren; 06.08.2014
comment
Я посмотрю, хорошо, у меня есть код и время работы, чтобы запустить его через полный набор данных и посмотреть, как мы пойдем! - person Methexis; 06.08.2014
comment
Просто любопытно, о каких событиях здесь идет речь? - person rsoren; 06.08.2014
comment
Торнадо! Я смотрю на вспышки, их кумулятивную энергию и ищу какую-либо корреляцию с сигналом ENSO. Расчет энергии, выбрасываемой за вспышку, и взаимосвязь со значением ЭНЮК был легким моментом. Я запустил и экспортировал в clusterpaticipant, теперь попробую этот второй шаг. - person Methexis; 06.08.2014
comment
Почти там, для ClusterParticipant, может ли первый кластер быть 1, второй 2, 3, 4, 5 ..... с макушки моей головы определить цикл, скажем, x и if (d[i, cluster] == х) как-то так! - person Methexis; 06.08.2014
comment
Вы хотите, чтобы смежные кластеры считались одним большим кластером, как в строках 7 и 8? - person rsoren; 06.08.2014
comment
Правильно.... если последний торнадо в кластере происходит => 6 с момента второго последнего, то они должны быть зарегистрированы как происходящие в одном кластере. Подумать только, мой начальник заставит меня сделать это в Excel вручную! - person Methexis; 06.08.2014
comment
другими словами, кластер определяется с помощью 0 в начале и в конце последовательности 1 в участнике кластера, но в идеале эта последовательность будет состоять из 1, 2, 3 и т. д. Таким образом, я могу генерировать уникальные идентификаторы кластера. - person Methexis; 06.08.2014
comment
Хорошо, я добавил цикл for, который назначает идентификаторы кластеров. Твой начальник купит мне пива, когда я в следующий раз буду в Лондоне :D - person rsoren; 06.08.2014
comment
ЭТО РАБОТАЕТ... это блестяще, да, пиво и, возможно, даже получит благодарность в описании! - person Methexis; 06.08.2014
comment
Отлично :) если вы не возражаете, опубликуйте копию отчета здесь, если решите процитировать этот пост. - person rsoren; 06.08.2014