确定有多少时间间隔与每个给定时间间隔(R)相交

确定有多少时间间隔与每个给定时间间隔(R)相交,r,interval-tree,R,Interval Tree,我正在使用R。这是前六行-不计算第一列,write.csv函数总是添加第一列-: > head(my_data) client_id contract_id contract_start contract_end inter_complex 1 1 15/07/2019 15/07/2020 18092+18458i 3 3 1/01/2015 1/01/2015 16436+16436

我正在使用R。这是前六行-不计算第一列,write.csv函数总是添加第一列-:

> head(my_data)
client_id contract_id contract_start contract_end inter_complex
        1           1     15/07/2019   15/07/2020  18092+18458i
        3           3      1/01/2015    1/01/2015  16436+16436i
        5           5     12/06/2020   12/06/2020  18425+18425i
       13          13      1/01/2015    1/01/2015  16436+16436i
       18          18      1/01/2015    1/01/2015  16436+16436i
       19          19      1/01/2015    1/01/2015  16436+16436i
每行代表不同的合同。变量inter_复数是一个复数,其实部是合同开始日期的数字表示,其虚部类似地表示合同结束日期。如果您想知道,您可以通过执行以下命令获得该列:

library(tidyverse)
library(lubridate)

chars_2_cplex = function(start, end) {
    cbind(start, end) %>%
    apply(2, compose(as.numeric, dmy)) %*% rbind(1, 1i)
}

my_data %>% transmute(inter_complex = chars_2_cplex(contract_start, contract_end))
my_data %>% group_by(client_id) %>% group_map(~ get_intersections(.x$inter_complex))
我想要的是,对于每个客户id和每个合同,识别与同一客户id相关联的合同与该合同相交的数量。换句话说:我想创建一个名为“同步”的新列,该列将为每一行(即,对于每个合同)描述相应客户在与当前合同相同的期间内有多少个活动合同活跃的如果给定合同未发现与任何其他合同的交叉点,则同步合同的价值必须为1,因为该合同处于活动状态时,它也是各客户拥有的唯一活动合同

我认为这将有助于获得inter_复数的组合,然后将这些复数组合转换为区间组合,然后使用lubridate的intersect函数来识别每个区间组合是否相交。为此,我编写了以下代码:

## This function turns complex numbers into intervals.
cplex_2_inter = function(x) {
    start = x %>% Re() %>% as.integer()
    end = x %>% Im() %>% as.integer()

    interval(as_date(start), as_date(end))
}


## This other function returns a list whose j-th element is a data frame that shows the interceptions
## between combinations of j + 1 intervals.
get_intersections = function(x) {
    max_m = length(x)
    output = vector(mode = "list", length = max_m - 1)

    for (i in 2:max_m) {
        output[[i - 1]] = combn(x, m = i) %>% t() %>% as.data.frame() %>% 
                          mutate_all(cplex_2_inter) %>% rowid_to_column("id") %>%
                          pivot_longer(-id) %>% group_by(id) %>% 
                          mutate(simultaneous = do.call(lubridate::intersect, as.list(value))) %>%
                          mutate(simultaneous = if_else(as.character(simultaneous) != "NA--NA", i, 1L))
    }

    return(output)
}
为了更好地理解函数get_crossions的作用,我建议您运行以下命令:

example = my_data %>% filter(client_id == 1) %>% pull(inter_complex) %>% get_intersections()
数据框
示例[[1]]
显示了间隔对之间是否存在截获,或者更确切地说,重叠。数据框
示例[[2]]
显示三个间隔的组之间是否存在重叠,依此类推

您可能会注意到,根据
示例[[1]]
的规定,2019-07-15 UTC--2020-07-15 UTC的时间间隔与其他时间间隔重叠,因此,同步的关联值为2,而根据
示例[[2]]
,相同的时间间隔与变量同步的值3相关联当然,我们的想法是为每个间隔分配最高的同时值。

因为我不关心全局重叠,而是关心每个客户机id内的重叠,所以我认为我需要处理分组数据帧。我在这个项目上做得最远的是写这篇文章:

library(tidyverse)
library(lubridate)

chars_2_cplex = function(start, end) {
    cbind(start, end) %>%
    apply(2, compose(as.numeric, dmy)) %*% rbind(1, 1i)
}

my_data %>% transmute(inter_complex = chars_2_cplex(contract_start, contract_end))
my_data %>% group_by(client_id) %>% group_map(~ get_intersections(.x$inter_complex))
现在谈谈我的问题1)我已经执行了上面的一行,但是这个过程不是很有效。它已经运行了一整天多一点,但还没有结束。最近我遇到了区间树的概念,但我不是一名计算机科学家,我需要帮助以更智能的方式解决这个问题2)如果我们坚持我不太聪明的方法来解决这个问题,我仍然需要一个函数来访问get_交叉点返回的列表中的每个元素,以便识别和检索与每个间隔相关的最高同时值。在那件事上,我也得请求帮助

编辑 关于Wimpel的回答,我检查了他们的数据表,发现了这个

> DT %>% filter(client_id == 502 & contract_id == 3093) %>%
> select(contract_start, contract_end, contract_intersect)
# Output
   contract_start contract_end contract_intersect
1:     2018-01-11   2019-01-11                  7
也就是说,所显示的合同据称与同一客户拥有的七个
其他合同重叠

另一方面,让我们看看在使用基于组合的方法时这是否成立

combs_10_502 = my_data %>% filter(client_id == 502) %>% pull(inter_complex) %>% 
               combn(10) %>% t() %>% as.data.frame() %>% mutate_all(cplex_2_inter) %>% 
               rowid_to_column("id") %>% pivot_longer(-id) %>% group_by(id) %>% 
               mutate(simultaneous = do.call(lubridate::intersect, as.list(value))) %>% 
               ungroup() %>% 
               mutate(simultaneous = if_else(as.character(simultaneous) != "NA--NA", 10L, 1L))    

> combs_10_502 %>% filter(simultaneous == 10) %>% slice(11:20)
# A tibble: 10 x 4
  id    name  value                          simultaneous
  <int> <chr> <Interval>                            <int>
1  24311 V1    2018-01-11 UTC--2019-01-11 UTC        10
2  24311 V2    2018-03-01 UTC--2019-03-01 UTC        10
3  24311 V3    2018-07-11 UTC--2019-07-11 UTC        10
4  24311 V4    2018-04-20 UTC--2019-04-20 UTC        10
5  24311 V5    2018-05-21 UTC--2019-05-21 UTC        10
6  24311 V6    2018-08-10 UTC--2019-08-10 UTC        10
7  24311 V7    2018-08-09 UTC--2019-08-09 UTC        10
8  24311 V8    2018-09-27 UTC--2019-09-27 UTC        10
9  24311 V9    2020-01-03 UTC--2021-01-03 UTC        10
10 24311 V10   2019-12-19 UTC--2020-12-19 UTC        10
combs\u 10\u 502=my\u data%%>%filter(client\u id==502)%%>%pull(inter\u complex)%%
combn(10)%%>%t()%%>%as.data.frame()%%>%mutate\u all(cplex\u 2\u inter)%%
行id到列(“id”)%%>%pivot\u更长(-id)%%>%group\u by(id)%%
mutate(同时=do.call(lubridate::intersect,as.list(value)))%>%
解组()%>%
变异(同时=如果其他(如字符(同时)!=“NA--NA”,10L,1L))
>梳齿10梳齿502%>%过滤器(同时==10)%>%切片(11:20)
#一个tibble:10x4
id名称值同步
1 24311 V1 2018-01-11 UTC--2019-01-11 UTC 10
2 24311 V2 2018-03-01 UTC--2019-03-01 UTC 10
3 24311 V3 2018-07-11 UTC--2019-07-11 UTC 10
4 24311 V4 2018-04-20 UTC--2019-04-20 UTC 10
5 24311 V5 2018-05-21 UTC--2019-05-21 UTC 10
6 24311 V6 2018-08-10 UTC--2019-08-10 UTC 10
7 24311 V7 2018-08-09 UTC--2019-08-09 UTC 10
8 24311 V8 2018-09-27 UTC--2019-09-27 UTC 10
9 24311 V9 2020-01-03 UTC--2021-01-03 UTC 10
10 24311 V10 2019-12-19 UTC--2020-12-19 UTC 10
相同的合同显示在上面TIBLE的第一行。可以看出,该合同实际上与给定客户的其他九份合同重叠,这九份合同显示在其余行中


我不知道Wimpel的解决方案是如何出错的,但我检查了一下,它确实为其他几个合同提供了正确的交叉口数量。现在我知道我正在寻找一个基于数据表的解决方案,因为过程非常快,但建议的解决方案似乎存在问题。

我相信您正在寻找类似的解决方案

library(data.table)
DT <- fread("https://raw.githubusercontent.com/pazos-feren/Data/main/contracts.csv")
#set dates as real dates
DT[, contract_start := as.Date(contract_start, format = "%d/%m/%Y")]
DT[, contract_end := as.Date(contract_end, format = "%d/%m/%Y")]

setkey(DT, V1)

DT[DT, c("contract_intersect", "contract_intersect_ids") := {
  val = DT[ !V1 == i.V1 & client_id == i.client_id &
              contract_start <= i.contract_end & contract_end >= i.contract_start, ]
  list( nrow(val), paste0(val$contract_id, collapse = ";") )
}, by = .EACHI]

#    V1 client_id contract_id contract_start contract_end inter_complex contract_intersect contract_intersect_ids
# 1:  1         1           1     2019-07-15   2020-07-15  18092+18458i                  2              4162;4168
# 2:  2         3           3     2015-01-01   2015-01-01  16436+16436i                  0                       
# 3:  3         5           5     2020-06-12   2020-06-12  18425+18425i                  0                       
# 4:  4        13          13     2015-01-01   2015-01-01  16436+16436i                  0                       
# 5:  5        18          18     2015-01-01   2015-01-01  16436+16436i                  0                       
# 6:  6        19          19     2015-01-01   2015-01-01  16436+16436i                  0                       
库(data.table)

DT我刚刚编辑了我的原始帖子,以解决我在您的解决方案中发现的一个问题。除此之外,我真的很感激你的回答,看来你已经很接近解决这个问题了。请您再看一下好吗?阅读您的编辑,可以看到一些我有疑问的地方:第1行
1 24311 V1 2018-01-11 UTC--2019-01-11 UTC 10
没有重叠第9行和/或第10行
10 24311 V10 2019-12-19 UTC--2020-12-19 UTC 10
。为什么这些合同在你的订单清单上