如何统计特定时间内“活跃”的项目数量?

问题描述 投票:0回答:2

背景

我有以下项目数据框架:

id 开始日期 结束日期
01 2019年6月11日 2021 年 4 月 7 日
02 2021 年 8 月 12 日 2022 年 1 月 18 日
03 2019/10/24 2019年12月3日
04 2021 年 9 月 20 日 2021 年 11 月 11 日
05 2021 年 11 月 11 日 2021 年 11 月 11 日

我还有一个日期列表:

date_list <- c(1/1/2020, 1/1/2021, 1/1,2022)

我想计算在这些特定日期内有多少项目处于“活跃”状态。

例如: 2020 年 1 月 1 日,只有 1 个项目处于活动状态,即项目#1,因为它在 2020 年 1 月 1 日之前开始并在 2020 年 1 月 1 日之后结束。换句话说,该日期是一个活跃的项目。

目前的做法

for (date in date-list) {
  projects %>% filter(start_date <= date & end_date > date) %>% count()
}

这花费了太长时间,因为我正在处理数千个日期的列表和数千个项目的列表。

r date count
2个回答
0
投票

您可以首先构建一个给定日期的所有开放项目的表。这是一种方法来做到这一点


number_open <- rbind(
  data.frame(date=dd$end_date+1, open=-1),
  data.frame(date=dd$start_date, open=1)
) %>%
  arrange(date) %>% 
  summarize(open=sum(open), .by=date) %>% 
  mutate(open=cumsum(open))

返回

        date open
1 2019-06-11    1
2 2019-10-24    2
3 2019-12-04    1
4 2021-04-08    0
5 2021-08-12    1
6 2021-09-20    2
7 2021-11-11    3
8 2021-11-12    1
9 2022-01-19    0

因此,对于每个日期,我们都可以看到项目数量何时发生变化。 我们可以使用

findInterval
对日期列表进行排序,以查找给定日期的开放事件数量

date_list <- as.Date(c("1/1/2020", "1/1/2021", "1/1/2022"), "%m/%d/%Y")
number_open$open[findInterval(date_list, number_open$date)]
# [1] 1 1 1

因此,每个日期都有 1 个项目处于开放状态。


0
投票

执行此操作的快速方法是使用

data.table::foverlaps()

library(data.table)

# Set keys for join
setkey(projects, start_date, end_date)
setkey(date_dt, date, dummy_date)

project_dates  <- foverlaps(projects, date_dt, type="any")
setorder(project_dates, id, start_date)
setcolorder(project_dates, c("id", "start_date", "end_date", "date"))
project_dates[, dummy_date := NULL]

project_dates
#       id start_date   end_date       date
#    <int>     <IDat>     <IDat>     <IDat>
# 1:     1 2019-06-11 2021-04-07 2020-01-01
# 2:     1 2019-06-11 2021-04-07 2021-01-01
# 3:     2 2021-08-12 2022-01-18 2022-01-01
# 4:     3 2019-10-24 2019-12-03       <NA>
# 5:     4 2021-09-20 2021-11-11       <NA>
# 6:     5 2021-11-11 2021-11-11       <NA>
© www.soinside.com 2019 - 2024. All rights reserved.