【问题标题】:R - Sliding Door Analysis # of events in time periodR - 滑动门分析时间段内的事件数
【发布时间】:2014-09-28 16:52:15
【问题描述】:

我重新发布这个问题是因为我认为我需要进行聚类类型分析,但需要更多的是“滑动窗口”分析。我有一个数据集,其中记录了超过 63 年的 59k 个条目,我需要识别事件的“集群”,其标准是:

由 6 个或更多事件组成的序列,序列中连续事件之间的间隔不超过 6 小时。

每个事件都有一个唯一的 ID 和一个日期/时间戳,理想情况下,输出会为满足上述条件的事件分配一个集群 ID。我一直针对滑动窗口方法,是最好的选择吗?也许使用 zoo 包中的 rollapply ?

如果有人感觉非常有帮助,我会添加一个为期一年的数据样本。 https://dl.dropboxusercontent.com/u/16400709/StackOverflow/DataStack.csv

我已经在 R 中看到了这样一个分析的输出,但目前还不能复制它,这个分析的结果可以在这篇论文中看到 --> https://dl.dropboxusercontent.com/u/16400709/StackOverflow/fuhrmann_etal_waf2014.pdf

感谢您的宝贵时间!

【问题讨论】:

    标签: r datetime cluster-analysis sliding-window rollapply


    【解决方案1】:

    这是使用zoo 包中的rollapply 的解决方案。

    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
    

    编辑:下面的代码用于给每个集群(或超集群)一个 ID 号。它创建变量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 }
    
    }
    

    【讨论】:

    • 我做了一个更改,应该为您正确读取数据,并且应该处理您提到的错误。只需将文件路径更改为您保留DataStack.csv 的位置。我使用d[] 是为了保留d 的数据帧结构,否则lapply 的结果将是一个列表。
    • 我从 Hadley Wickham 的优秀在线(免费)书籍“Advanced R”(adv-r.had.co.nz) 中了解到这一点。如果您有时间完成它,强烈推荐。
    • 只是好奇,我们在这里谈论什么样的“事件”?
    • 您是否希望将相邻的集群视为一个大集群,如第 7 行和第 8 行所示?
    • 好的,我添加了一个分配集群 ID 的 for 循环。下次我在伦敦时,你的主管可以请我喝啤酒:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 2012-05-15
    • 2021-04-19
    • 1970-01-01
    相关资源
    最近更新 更多