将事件与日期范围进行时间关联

Temporally correlating events with date ranges

提问人:Kaila Frazer 提问时间:10/20/2023 更新时间:11/3/2023 访问量:57

问:

我在 R 中有一个极端温度事件的数据帧。数据如下所示:

data <- data.frame(date_start = c("1980-05-11", "1980-07-12", "1980-08-17", "1980-05-10", "1980-05-23"), date_end = c("1980-06-27", "1980-07-29", "1980-09-03", "1980-05-19", "1980-06-27"), lat = (c(31, 31, 31, 32, 32)), lon = c(-119, -119, -119, -120, -120)) # Create dummy data
data$date_start <- as.Date(data$date_start) ; data$date_end <- as.Date(data$date_end)

data
#  date_start   date_end lat  lon
# 1 1980-05-11 1980-06-27  31 -119
# 2 1980-07-12 1980-07-29  31 -119
# 3 1980-08-17 1980-09-03  31 -119
# 4 1980-05-10 1980-05-19  32 -120
# 5 1980-05-23 1980-06-27  32 -120

我想将事件与重叠的时间窗口(即第 1 行和第 4 行中的事件)相关联。目标是了解每个事件的空间范围(它延伸了多少个纬度/纬度值)。

给定date_start值和date_end值,将数据集分组为并发发生的事件的最佳方法是什么?

我尝试遍历每一天感兴趣的事件并提取当天的事件,但随后我必须将我的事件关联到各个日期。这种方法的效率也很低。

我认为这篇文章中可能会有一些有用的内容,但这并不能让我达到我需要的位置,因为我的事件有一个日期范围,而不是每个事件的单个日期。

任何想法将不胜感激!

R 日期 时间序列 分组 相关性

评论


答:

1赞 Ben 10/21/2023 #1

下面是 的一种方法。您可以按开始日期和结束日期划分数据,然后在开始日期超过运行最大结束日期时分配递增的组号。这会将日期范围重叠的第 1、4、5 行分组到一个组 (1) 中。data.tableorder

library(data.table)

setDT(data)
data[order(date_start, date_end), group := cumsum(date_start > shift(cummax(as.integer(date_end)), fill = 0))]
data

输出

   date_start   date_end lat  lon group
1: 1980-05-11 1980-06-27  31 -119     1
2: 1980-07-12 1980-07-29  31 -119     2
3: 1980-08-17 1980-09-03  31 -119     3
4: 1980-05-10 1980-05-19  32 -120     1
5: 1980-05-23 1980-06-27  32 -120     1

评论

0赞 Kaila Frazer 10/22/2023
这非常有用,非常感谢@Ben。它几乎完美地工作,除了一组日期略微重叠。这个组包括四个不同的日期范围(1980 年的 5 月、6 月、7 月和 8 月),我不知道为什么。结束日期与开始日期没有重叠......知道为什么会发生这种情况吗?
0赞 Ben 10/22/2023
@KailaFrazer 很高兴听到它很有帮助。很难从描述中看出发生了什么。如果您能够重现该问题,则可以编辑原始帖子/问题并进一步描述它(也许可以使用示例数据来演示)。一种想法是,您可以将多个日期范围全部链接在一起 - 只需要一个大的重叠范围,它就会将所有与之重叠的小范围分组到一个组中。
0赞 Davis Vaughan 11/3/2023 #2

另一种可能的解决方案是使用 ivs 包,它是专门为处理这样的区间数据而创建的。

library(ivs)

data <- data.frame(date_start = c("1980-05-11", "1980-07-12", "1980-08-17", "1980-05-10", "1980-05-23"), date_end = c("1980-06-27", "1980-07-29", "1980-09-03", "1980-05-19", "1980-06-27"), lat = (c(31, 31, 31, 32, 32)), lon = c(-119, -119, -119, -120, -120)) # Create dummy data
data$date_start <- as.Date(data$date_start)
data$date_end <- as.Date(data$date_end)

# Merge [start, end) into an interval object
data$range <- iv(data$date_start, data$date_end)
data$date_start <- NULL
data$date_end <- NULL

# Identify the interval "group" that each row falls in
data$group <- iv_identify_group(data$range)

# Optionally, turn that into an integer id for grouping
# (but you could also group on `group`)
data$id <- vctrs::vec_group_id(data$group)

data
#>   lat  lon                    range                    group id
#> 1  31 -119 [1980-05-11, 1980-06-27) [1980-05-10, 1980-06-27)  1
#> 2  31 -119 [1980-07-12, 1980-07-29) [1980-07-12, 1980-07-29)  2
#> 3  31 -119 [1980-08-17, 1980-09-03) [1980-08-17, 1980-09-03)  3
#> 4  32 -120 [1980-05-10, 1980-05-19) [1980-05-10, 1980-06-27)  1
#> 5  32 -120 [1980-05-23, 1980-06-27) [1980-05-10, 1980-06-27)  1