如何对顺序事件时间序列(事件之间有中断)进行分组以查找事件的持续时间

How to group sequential event time sequences (with breaks between events) to find duration of events

我在 R 中有一个数据集,其中包含一系列人物、发生的事件以及它们发生的指定时间(以秒为单位,从 0 开始)。它看起来类似于:

event seconds person
1      0.0    Bob
2     15.0    Bob
3     28.5    Bob
4     32.0    Joe
5     38.0    Joe
6     41.0    Joe
7     42.5    Joe
8     55.0    Anne
9     58.0    Anne

我需要对每个名字进行过滤,这意味着为每个人排序的事件不会按顺序排列。

这看起来像一个例子(注意鲍勃如何不参与事件 4-40 等):

event seconds person
1      0.0     Bob
2      15.0    Bob
3      28.5    Bob
41     256.0   Bob
42     261.0   Bob
43     266.0   Bob
44     268.5   Bob
45     272.0   Bob
46     273.0   Bob
49     569.0   Bob
80     570.5   Bob
81     581.0   Bob

顺序相关的事件以1为增量分隔。我想找到相关事件的持续时间,例如事件1-3是一组,即28.5秒。事件 41-46 是另一组,持续 17 秒。这对于人员列中列出的所有姓名都是必需的。

我尝试使用 dplyr 过滤名称,然后使用 as.matrix 找出事件行之间的差异,并确定增量大于 1 的位置(表明它不再是当前事件序列的一部分) ).我还没有找到一种方法来根据此分配最大值和最小值来确定相关事件的持续时间。虽然解决方案不需要涉及此步骤,但这是我能想到的最接近的步骤。

最终目标是绘制每个人的非连续持续时间,以便直观地表示每个人对整个数据集的事件参与情况。

提前谢谢你。

使用这个:

DF <- read.table(text = "event seconds person
                 1      0.0     Bob
                 2      15.0    Bob
                 3      28.5    Bob
                 41     256.0   Bob
                 42     261.0   Bob
                 43     266.0   Bob
                 44     268.5   Bob
                 45     272.0   Bob
                 46     273.0   Bob
                 49     569.0   Bob
                 80     570.5   Bob
                 81     581.0   Bob", header = TRUE)

DF$personEvent <- cumsum(c(1L, diff(DF$event)) != 1L)
#   event seconds person personEvent
#1      1     0.0    Bob           0
#2      2    15.0    Bob           0
#3      3    28.5    Bob           0
#4     41   256.0    Bob           1
#5     42   261.0    Bob           1
#6     43   266.0    Bob           1
#7     44   268.5    Bob           1
#8     45   272.0    Bob           1
#9     46   273.0    Bob           1
#10    49   569.0    Bob           2
#11    80   570.5    Bob           3
#12    81   581.0    Bob           3

既然我不是大烟斗的追随者,剩下的就交给你了。

假设首先我们只有 Bob 的数据框行,称为 bob。 我们假设 bob 已经由 event 订购,递增。

按照您提到的相同思路(查看 diff(event) > 1),您还可以使用 cumsum 将每个事件分组到它所属的 'run' 个事件中:

library(plyr)
bob2 <- mutate(bob, start = c(1, diff(bob$event) > 1), run=cumsum(start))
   event seconds person start run
1      1     0.0    Bob     1   1
2      2    15.0    Bob     0   1
3      3    28.5    Bob     0   1
4     41   256.0    Bob     1   2
5     42   261.0    Bob     0   2
6     43   266.0    Bob     0   2
7     44   268.5    Bob     0   2
8     45   272.0    Bob     0   2
9     46   273.0    Bob     0   2
10    49   569.0    Bob     1   3
11    80   570.5    Bob     1   4
12    81   581.0    Bob     0   4

start 表示这是否启动了 运行 个连续事件,run 是我们所处的事件集。

那么你就可以找到持续时间:

ddply(bob2, .(run), summarize, length=diff(range(seconds)))
  run length
1   1   28.5
2   2   17.0
3   3    0.0
4   4   10.5

现在假设你有原始数据框,每个人都混合在一起,我们可以再次使用 ddply 将其按人拆分:

tmp <- ddply(df, .(person), transform, run=cumsum(c(1, diff(event) != 1)))
ddply(tmp, .(person, run), summarize, length=diff(range(seconds)), start_event=first(event), end_event=last(event))

    person run length start_event end_event
1   Anne   1    3.0           8         9
2    Bob   1   28.5           1         3
3    Bob   2   17.0          41        46
4    Bob   3    0.0          49        49
5    Bob   4   10.5          80        81
6    Joe   1   10.5           4         7

注意:我的 df 是你的 bob table rbind-ed 到你的另一个 table, unique()d(只是为了证明当有超过每人 运行 个)。 可能有一种巧妙的方法可以结合两个 ddply 调用(或使用我不熟悉的 dplyr pipe-y 语法),但我不知道它是什么。