r - 计算日期范围间隔的部分重叠数
问题描述
我需要在大约 150K 行的数据帧上运行一个循环。但是,循环需要检查每一行并检查一个条件,该条件检查数据集中的每隔一行。我的代码适用于玩具数据集,它产生正确的值,但对于我的实际数据集来说太慢了。我让它运行了几个小时,它仍然没有完成。所以我希望有人对如何解决这个问题有更好的了解。
#R version 3.5.1 Windows 64-bit
#Example dataset
my_df <- data.frame("PERSON" = c("A","A","A","B","A","A","B"),
"DATE_START" = c("2019-01-15","2019-01-10","2019-01-20","2019-01-19","2018-12-20","2018-03-03","2019-05-01"),
"DATE_FINISH" = c("2019-01-30","2019-01-18","2019-02-05","2019-01-23","2019-02-10","2018-04-01","2019-06-06")
)
#Each row is a task that the assigned person is working on
my_df
PERSON DATE_START DATE_FINISH
1 A 2019-01-15 2019-01-30
2 A 2019-01-10 2019-01-18
3 A 2019-01-20 2019-02-05
4 B 2019-01-19 2019-01-23
5 A 2018-12-20 2019-02-10
6 A 2018-03-03 2018-04-01
7 B 2019-05-01 2019-06-06
我想知道的是对于第 1 行,A 人的开始日期和结束日期之间还有多少其他任务重叠?(包括其所在的行)
所以我正在寻找的答案是
PERSON DATE_START DATE_FINISH NUMBER_OF_TASKS
1 A 2019-01-15 2019-01-30 4
2 A 2019-01-10 2019-01-18 3
3 A 2019-01-20 2019-02-05 3
4 B 2019-01-19 2019-01-23 1
5 A 2018-12-20 2019-02-10 4
6 A 2018-03-03 2018-04-01 1
7 B 2019-05-01 2019-06-06 1
所以这基本上说对于第 1 行,人 A 有 4 个未完成的任务
我尝试为包含日期范围作为数值的每一行创建列表元素,然后检查是否存在重叠我使用 %in% 运算符来比较未列出的范围
我使用 lapply 函数(此处未显示)做了类似的事情,但同样的问题只需要永远执行。
##This is what I currently have
temp_list <- list()
num_open_tasks <- c()
open_work_cc <- c()
##Create a list of length = nrow(my_df)
##Each element in the list is a range of dates coerced to numeric
for(i in 1:nrow(my_df)){
temp_list[[i]] <- as.numeric(my_df$DATE_START[i]) :
as.numeric(my_df$DATE_FINISH[i])
}
for(i in 1:nrow(my_df)){
for(j in 1:nrow(my_df)){
##If elements from the temp_list overlap by 5 days, the overlap = 5
##I'm just checking if the overlap is greater than 0 (is there any overlap at all)
##And if the tasks belongs to the same person or not
open_work_cc[j] <- ifelse(sum(unlist(temp_list[[i]]) %in%
unlist(temp_list[[j]])) > 0 &
my_df$PERSON[i] == my_df$PERSON[j]
,1,0
)
open_work_cc_total <- sum(open_work_cc)
}
num_open_tasks[i] <- open_work_cc_total
}
my_df <- cbind(my_df, num_open_tasks)
此方法返回填充了正确值的所需列。但我想有一种更优雅、更快速的方法,使用某种形式的拆分/应用/组合。感谢任何和所有帮助
解决方案
foverlaps
indata.table
可能是 R 中最快的方法。我认为以下代码可以满足您的要求:
library(data.table)
setDT(my_df)
my_df[, DATE_START_N:=as.numeric(as.Date(DATE_START))]
my_df[, DATE_FINISH_N:=as.numeric(as.Date(DATE_FINISH))]
setkey(my_df, PERSON, DATE_START_N,DATE_FINISH_N)
my_df[,NUMBER_OF_TASKS:=foverlaps(my_df,my_df,which=TRUE)[,.N,by=xid]$N]
my_df
为了更清楚一点:foverlaps(my_df,my_df,which=TRUE)
在日期范围内进行自连接PERSON
(连接由 确定setkey
)。请注意,type
foverlaps 的间隔连接的默认参数是间隔"any"
的部分匹配:即,您想要的。
指定which=TRUE
将仅提供 x 和 y 中匹配的索引(而不是此处不需要的实际连接数据)。调用foverlaps
返回一个类对象,data.table
然后立即聚合该对象,以使用方括号函数调用获取由xid
(只是 的行)定义的每个组中的行数。这些计数被提取到一个向量中,并分配给 中的一个新列。my_df
[,.N,by=xid]
$N
NUMBER_OF_TASKS
my_df
推荐阅读
- java - 在 Intelij 中为 Maven 项目创建运行配置?
- html - 为什么我的 favicon 在我的下一个 js 应用程序中不起作用?
- java - OPC UA 调用确认方法并在 java 中获取 Bad_EventIdUnkown
- sql - 如何将array_agg之后的整数数组转换为IN子句的值
- whitespace - 如何在 sphinx 文档中显式呈现空格?
- json - 自定义连接器(JSON 结果转换为参数)
- system-verilog - 在systemverilog中实现关联数组队列的正确方法是什么?
- php - 如何在 WooCommerce 中四舍五入价格?
- excel - 在各个单元格中显示结果,而不是弹出消息框
- javascript - 文本轮播过渡