我有一个 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
我想将事件与重叠的时间窗口关联起来(即第一行和第四行中的事件)。目标是了解每个事件的空间范围(它延伸了多少纬度/经度值)。
给定 date_start 和 date_end 值,将我的数据集分组为同时发生的事件的最佳方法是什么?
我尝试循环遍历感兴趣的每一天并提取当天的事件,但随后我必须将不同日期的事件关联起来。这种方法效率也很低。
我认为这篇文章中可能有一些有用的内容,但这并不能完全满足我的需要,因为我的活动有一个日期范围,而不是每个活动都有一个日期。
任何想法将不胜感激!
这是一种使用
data.table
的方法。您可以按开始日期和结束日期order
排列数据,然后在开始日期超过运行的最大结束日期时分配递增的组编号。这会将具有重叠日期范围的第 1、4、5 行分组为一个组 (1)。
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
另一种可能的解决方案是使用 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