分析R中重复序列中事件之间的时差

分析R中重复序列中事件之间的时差,r,data.table,R,Data.table,我有一个按日期时间排序的数据表,如下所示,我想分析ID=1和ID的2到5之间的时间差,由状态和状态的重复序列分隔 structure(list(DateTime = structure(c(1533081601.42, 1533081601.98, 1533081601.98, 1533081601.98, 1533081602.02, 1533081928.06, 1533081928.22,

我有一个按日期时间排序的
数据表,如下所示,我想分析ID=1和ID的2到5之间的时间差,由状态和状态的重复序列分隔

structure(list(DateTime = structure(c(1533081601.42, 1533081601.98, 
                                      1533081601.98, 1533081601.98, 1533081602.02, 1533081928.06, 1533081928.22, 
                                      1533081928.22, 1533081928.22, 1533081928.22, 1533081952.34, 1533081952.94, 
                                      1533081952.94, 1533081952.94, 1533081952.98, 1533081953.98, 1533081954.14, 
                                      1533081954.14, 1533081954.14, 1533081954.14), class = c("POSIXct", 
                                                                                              "POSIXt"), tzone = "UTC"), ID = c(1, 3, 4, 5, 2, 1, 2, 3, 4, 
                                                                                                                                5, 1, 3, 4, 5, 2, 1, 2, 3, 4, 5), state = c(0L, 0L, 0L, 0L, 0L, 
                                                                                                                                                                            1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L)), class = c("data.table", 
                                                                                                                                                                                                                                                    "data.frame"))
ID 1始终是序列中的第一个,但ID 1之后的ID 2-5的顺序正在更改。状态序列只是0和1的重复

对于具有相同状态(1或0)的IDs1到5的每次运行,我希望获得ID1和其他ID之间的时间差


首选
data.table()
方法,但欢迎任何建议

使用原始表格副本的解决方案:

dt<-
structure(list(DateTime = structure(c(1533081601.42, 1533081601.98, 
                                      1533081601.98, 1533081601.98, 1533081602.02, 1533081928.06, 1533081928.22, 
                                      1533081928.22, 1533081928.22, 1533081928.22, 1533081952.34, 1533081952.94, 
                                      1533081952.94, 1533081952.94, 1533081952.98, 1533081953.98, 1533081954.14, 
                                      1533081954.14, 1533081954.14, 1533081954.14), class = c("POSIXct", 
                                                                                              "POSIXt"), tzone = "UTC"), ID = c(1, 3, 4, 5, 2, 1, 2, 3, 4, 
                                                                                                                                5, 1, 3, 4, 5, 2, 1, 2, 3, 4, 5), state = c(0L, 0L, 0L, 0L, 0L, 
                                                                                                                                                                            1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L)), class = c("data.table", 
                                                                                                                                                                                                                                                    "data.frame"))

setorder(dt,ID,DateTime)
dt[,run:=1:.N,by=ID]
dt2 = copy(dt)
dt3 = merge(dt[ID==1],dt2,by=c("state","run"),allow.cartesian=T)
dt3[,timediff:=DateTime.y -DateTime.x]
dt4 = dt3[ID.x==1 & ID.y %in% c(2:5)]
setnames(dt4,c("DateTime.y","ID.y"),c("DateTime","ID"))
result = merge(dt,dt4[,list(DateTime,ID,state,run,timediff)],by=c("DateTime","ID","state","run"),all.x=T)

dt使用原始表格副本的解决方案:

dt<-
structure(list(DateTime = structure(c(1533081601.42, 1533081601.98, 
                                      1533081601.98, 1533081601.98, 1533081602.02, 1533081928.06, 1533081928.22, 
                                      1533081928.22, 1533081928.22, 1533081928.22, 1533081952.34, 1533081952.94, 
                                      1533081952.94, 1533081952.94, 1533081952.98, 1533081953.98, 1533081954.14, 
                                      1533081954.14, 1533081954.14, 1533081954.14), class = c("POSIXct", 
                                                                                              "POSIXt"), tzone = "UTC"), ID = c(1, 3, 4, 5, 2, 1, 2, 3, 4, 
                                                                                                                                5, 1, 3, 4, 5, 2, 1, 2, 3, 4, 5), state = c(0L, 0L, 0L, 0L, 0L, 
                                                                                                                                                                            1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L)), class = c("data.table", 
                                                                                                                                                                                                                                                    "data.frame"))

setorder(dt,ID,DateTime)
dt[,run:=1:.N,by=ID]
dt2 = copy(dt)
dt3 = merge(dt[ID==1],dt2,by=c("state","run"),allow.cartesian=T)
dt3[,timediff:=DateTime.y -DateTime.x]
dt4 = dt3[ID.x==1 & ID.y %in% c(2:5)]
setnames(dt4,c("DateTime.y","ID.y"),c("DateTime","ID"))
result = merge(dt,dt4[,list(DateTime,ID,state,run,timediff)],by=c("DateTime","ID","state","run"),all.x=T)

dt假设数据的顺序正确

library(data.table)
df[, time_diff := round(DateTime - first(DateTime), 3L), by = cumsum(ID == 1)][]
会回来的

分组变量是通过
by=cumsum(ID==1)
动态创建的,因此每当遇到ID1时,它都会被提升。然后,通过引用创建一个新列,即不复制整个数据对象

由于每个组都以ID1开头,我们可以安全地使用
first(DateTime)
而不是
DateTime[ID==1]
从而避免了另一个查找操作。

假设数据的顺序正确

library(data.table)
df[, time_diff := round(DateTime - first(DateTime), 3L), by = cumsum(ID == 1)][]
会回来的

分组变量是通过
by=cumsum(ID==1)
动态创建的,因此每当遇到ID1时,它都会被提升。然后,通过引用创建一个新列,即不复制整个数据对象

由于每个组都以ID1开头,我们可以安全地使用
first(DateTime)
而不是
DateTime[ID==1]
从而避免了另一个查找操作。

是保证从ID1到下一个ID1的每次运行都具有相同的状态,还是要求它们具有相同的状态?确切地说,从ID 1到下一个ID 1的每次运行都具有相同的状态。是保证从ID 1到下一个ID 1的每次运行都具有相同的状态,还是要求它们具有相同的状态?确切地说,从ID 1到下一个ID 1的每次运行都具有相同的状态。工作完美且快速!我的第一种方法是使用rle()获得分组,但这是一种更高级的方法。非常感谢。事实上,我打算提出一种替代方法,使用
rleid(state)
进行分组。但是,如果有两个后续组具有相同的状态,那么这可能会失败。根据问题描述,查找ID1的出现似乎更安全。是的,状态是一个额外信息。不过,我还需要考虑那里的问题,但这是在数据清洗过程中发生之前,来到这个问题!再次感谢你+答案为1(有一个非常相似的答案,因此将其删除);我之所以写这篇文章,是因为我认为
rleid
不仅会导致问题,而且速度也可能较慢,所以除非真的需要
cumsum
在我看来是不应该被避免的。工作完美且快速!我的第一种方法是使用rle()获得分组,但这是一种更高级的方法。非常感谢。事实上,我打算提出一种替代方法,使用
rleid(state)
进行分组。但是,如果有两个后续组具有相同的状态,那么这可能会失败。根据问题描述,查找ID1的出现似乎更安全。是的,状态是一个额外信息。不过,我还需要考虑那里的问题,但这是在数据清洗过程中发生之前,来到这个问题!再次感谢你+答案为1(有一个非常相似的答案,因此将其删除);我之所以写这篇文章,是因为我认为
rleid
不仅会导致问题,而且速度也可能较慢,所以除非真的需要
cumsum
,否则在我看来不应该避免。这也行得通,但正如你提到的,我的数据集非常庞大(机器日志数据)。但感谢您发布解决方案!这同样有效,但正如您提到的,我的数据集非常庞大(机器日志数据)。但感谢您发布解决方案!