我正在尝试确定两次观察之间的时差。数据由不同的人分解,每个人都有自己唯一的ID。我有一个数据集,告诉我每次更改时状态更新,以及状态更改的时间。状态可以是两个值中的一个,并且它总是更改为它不是的值(在这种情况下,从Y到N,或从N到Y)。
数据如下所示:
ID Status Time
1 Y 2013-07-01 08:07:00
2 Y 2013-07-01 08:07:03
3 Y 2013-07-01 08:07:04
4 Y 2013-07-01 08:07:06
1 N 2013-07-01 08:07:07
2 N 2013-07-01 08:07:23
5 Y 2013-07-01 08:07:34
6 Y 2013-07-01 08:07:45
7 Y 2013-07-01 08:07:47
1 Y 2013-07-01 08:07:56
3 N 2013-07-01 08:07:58
我想要找到的是每个个人ID的每个状态更改之间经过的时间量 - 也就是说,从Y到N的时间长度。然后获取摘要统计信息,例如已过去的分布时间,经过时间的平均值等。
因此示例输出可能如下所示,记录上面发生的三个Y到N个开关(1个切换,2个切换,3个切换)
Y to N change Time elapsed (in seconds)
1 7
2 20
3 54
由于某种原因,我遇到了很多麻烦。现在我有POSIXlt格式的时间,ID和状态作为一个因素。我已经尝试使用ddply按ID排序数据,然后按时间戳排序,但到目前为止还没有用。任何建议将不胜感激!
编辑:将时间更改为实际处于正确的类型。
Edit2:在等待更多答案时最终编写了一个解决方案。我的方式比这里的许多解决方案更丑陋,但我做到了:
N <- ifelse(df$Status=="N",1,0)
Y <- ifelse(df$Status== "Y",1,0)
#making a vector which is 1 for a row if the item status of the row below it is N
var1 <- N
for (i in 1:nrow(df)) {
var1[i] <- N[i+1]
}
#making a vector which is TRUE if a row's item status is Y and the row after is N
check <- ifelse(var1==s & var1==1,TRUE,FALSE)
#had to define the last one as FALSE manually because the for loop above would miss the last entry due to how it was constructed
check [50000]=FALSE
#made a loop which finds the time difference for a row's TIME and the row below it, given that "check " is true for that row, and writes that to a results vector.
#here is the results vector
results <- numeric(nrow(df))
#here is the for loop
for (i in 1:nrow(df)) {
if(check [i]){
results[i] <- difftime(df$Time[i],df$Time[i+1])
}
}
我最初用for循环解决了这个问题,但是在我的实际数据集的大约100万行中它太慢了,所以我做了这个矢量化的东西。这些其他解决方案是否可以处理大数据?我一定会尝试出来的!
答案 0 :(得分:4)
这是另一种方法。我试图将所有数据保留在最终输出中。请注意,出于演示目的,我稍微修改了您的数据。在我的代码中,我首先按ID
和Time
排列数据。然后,我将Status
(即Y和N)更改为0和1以创建group
。在此group
可以告诉我们Status
何时发生了变化。如果您看到几行中的相同数字,则表示Status
未更改。然后,我计算每个ID的时间差(即gap
)。最后,我将每个组的第一行中没有出现的gap
值更改为NA。也就是说,我做了不必要的差距。请注意,每个ID的第一次观察也在gap
中有NA。 gap
排在第二位。
ann <- data.frame(ID = c(1,2,3,4,1,2,2,1,1,1,3),
Status = c("Y", "Y", "Y", "Y",
"N", "N", "Y", "Y", "Y", "N", "N"),
Time = c("2013-07-01 08:07:00", "2013-07-01 08:07:03",
"2013-07-01 08:07:04", "2013-07-01 08:07:06",
"2013-07-01 08:07:07", "2013-07-01 08:07:23",
"2013-07-01 08:07:34", "2013-07-01 08:07:45",
"2013-07-01 08:07:47", "2013-07-01 08:07:56",
"2013-07-01 08:07:58"),
stringsAsFactors = FALSE)
ann$Time <- as.POSIXct(ann$Time)
# ID Status Time
#1 1 Y 2013-07-01 08:07:00
#2 2 Y 2013-07-01 08:07:03
#3 3 Y 2013-07-01 08:07:04
#4 4 Y 2013-07-01 08:07:06
#5 1 N 2013-07-01 08:07:07
#6 2 N 2013-07-01 08:07:23
#7 2 Y 2013-07-01 08:07:34
#8 1 Y 2013-07-01 08:07:45
#9 1 Y 2013-07-01 08:07:47
#10 1 N 2013-07-01 08:07:56
#11 3 N 2013-07-01 08:07:58
ann %>%
arrange(ID, Time) %>%
group_by(ID) %>%
mutate(Status = ifelse(Status == "Y", 1, 0),
group = cumsum(c(T, diff(Status) != 0)),
gap = Time - lag(Time)) %>%
group_by(ID, group) %>%
mutate(gap = ifelse(row_number() != 1, NA, gap))
# ID Status Time group gap
#1 1 1 2013-07-01 08:07:00 1 NA
#2 1 0 2013-07-01 08:07:07 2 7
#3 1 1 2013-07-01 08:07:45 3 38
#4 1 1 2013-07-01 08:07:47 3 NA
#5 1 0 2013-07-01 08:07:56 4 9
#6 2 1 2013-07-01 08:07:03 1 NA
#7 2 0 2013-07-01 08:07:23 2 20
#8 2 1 2013-07-01 08:07:34 3 11
#9 3 1 2013-07-01 08:07:04 1 NA
#10 3 0 2013-07-01 08:07:58 2 54
#11 4 1 2013-07-01 08:07:06 1 NA
答案 1 :(得分:2)
这似乎适用于您提供的示例数据,但这些时间不是POSIXlt。这会找到第一个Y
时间和第一个N
时间,删除任何没有从Y
到N
的转换的ID,并减去第一个{{1}从第一个Y
时间开始的时间。
N
结果:
library('dplyr')
df <- read.table(text = "ID Status Time
1 Y 1
2 Y 2
3 Y 3.5
4 Y 4
1 N 5.8
2 N 6
5 Y 7
6 Y 8
7 Y 8.1
1 Y 11
3 N 12", header = TRUE)
df$ID <- as.factor(df$ID) # convert ID to factor
df %>%
group_by(ID, Status) %>%
summarize(Time = min(Time)) %>%
filter("N" %in% Status & "Y" %in% Status) %>%
summarize(Time_elapsed = Time[Status == "N"] - Time[Status == "Y"])