我的数据集中有三列用于解决这个问题。
第一列称为缓冲区,显示动物的 GPS 点是否在缓冲区内(是/否值)。第二个是动物 GPS 点的日期时间,第三个是在缓冲区内花费的时间 (dt1)。
我想做的是,如果缓冲区列中有一个“是”行,在两个“否”行之间,我想计算这个 GPS 点与前一个 GPS 点之间的时间差并将其打印在 dt1 上,我成功了。
问题是当我在查看多个连续的“是”行时尝试计算第一个和最后一个“是”行之间的时间差时,这意味着动物在缓冲区中停留的时间更长,因此连续的 GPS 点是在缓冲区内。
在这里你可以看到我的代码。问题在于,它为跟随其他“是”行的“是”行返回“NA”,基本上是任何未隔离的“是”行。我正在尝试获取“是行”系列中最后“是”行的总体时间差。
trips_with_buffer_2016_df <- trips_with_buffer_2016_df %>%
group_by(tripID) %>%
mutate(
dt1 = ifelse(buffer == 'yes',
ifelse(lag(buffer, default = 'no') == 'no',
difftime(DateTime, lag(DateTime), units = "mins"),
cumsum(as.numeric(difftime(DateTime, lag(DateTime,), units = "mins")))
),
NA_real_)
)
“tripID”列按之前识别的行程对 GPS 点进行分组。
如果您有唯一的行程 ID,我认为您不需要使用嵌套的 ifelse,您应该能够总结并获取每次行程的最小/最大时间,并据此计算 difftime。
trips_with_buffer_2016_df <- trips_with_buffer_2016_df %>%
group_by(tripID, buffer) %>%
summarise(MIN_TIME=min(DateTime), MAX_TIME=max(DateTime)) %>%
mutate(dt1=difftime(MAX_TIME, MIN_TIME, units="mins"))
您可以使用
rle
简化缓冲区内或缓冲区外的索引,
这里 0 = 出,1 = 入,但也可以是“是”、“否”
buffer = c(1,0,0,0,1,1,1,1,0,0,0,0,1,0,0,1,1,1,1,1,0,0)
rle(buffer)
Run Length Encoding
lengths: int [1:8] 1 3 4 4 1 2 5 2
values : num [1:8] 1 0 1 0 1 0 1 0
end = cumsum(rle(buffer)$lengths)
end
[1] 1 4 8 12 13 15 20 22
start = end - rle(buffer)$lengths +1
start
[1] 1 2 5 9 13 14 16 21
inbuf = which(rle(buffer)$values == 1)
inbuf
[1] 1 3 5 7
start[inbuf]
[1] 1 5 13 16
end[inbuf]
[1] 1 8 13 20
time = seq(5, 110, 5)
sum(diff(time[start[inbuf][2]:end[inbuf][2]]))
[1] 15
另一种思考方式,当事情几乎被遗忘并弹出错误时,可能更容易看到将来发生的事情。