按组合并多个时间间隔列的重叠部分

3

几天前我开了一个相关的帖子:Time-interval overlap match by group

然而,现在我需要处理这样一个事实:我需要重叠多个时间间隔列,并在发生重叠时返回标志=1的第一个行号值。

例如,我有以下数据框:

id    flag  row_number         time_1                             time_2              result
 1      1       1       2001-04-01 UTC--2001-05-01 UTC  1960-01-01 UTC--1962-01-01 UTC  NA
 1      1       2       2007-08-01 UTC--2007-12-01 UTC  1980-01-01 UTC--1982-01-01 UTC  NA
 1      1       3       2010-03-01 UTC--2011-03-01 UTC  1949-01-01 UTC--1951-01-01 UTC  NA
 1      0       4       2001-04-15 UTC--2001-04-20 UTC  1981-01-01 UTC--1983-01-01 UTC  NA
 1      0       5       2001-04-17 UTC--2001-05-15 UTC  1959-01-01 UTC--1961-01-01 UTC  1
 1      0       6       2007-09-01 UTC--2007-12-01 UTC  1980-01-01 UTC--1983-01-01 UTC  2
 1      0       7       2011-01-01 UTC--2011-03-05 UTC  1994-01-01 UTC--1996-01-01 UTC  NA
 1      0       8       2018-01-01 UTC--2017-12-01 UTC  1949-01-01 UTC--1951-01-01 UTC  NA

使用以下代码创建:

library(dplyr)
library(purrr)
library(lubridate)

df <- data.frame(id=c(1, 1, 1, 1, 1, 1, 1, 1),     
             flag=c(1, 1, 1, 0, 0, 0, 0, 0),
             row_number=c(1,2,3,4,5,6,7,8),
             time_1=c(interval(ymd(20010401), ymd(20010501)),
                    interval(ymd(20070801), ymd(20071201)), 
                    interval(ymd(20100301), ymd(20110301)), 
                    interval(ymd(20010415), ymd(20010420)), 
                    interval(ymd(20010417), ymd(20010515)),
                    interval(ymd(20070801), ymd(20071201)),
                    interval(ymd(20110101), ymd(20110305)),
                    interval(ymd(20180101), ymd(20171201))),
             time_2=c(interval(ymd(19600101), ymd(19620101)),
                      interval(ymd(19800101), ymd(19820101)), 
                      interval(ymd(19490101), ymd(19510101)), 
                      interval(ymd(19810101), ymd(19830101)), 
                      interval(ymd(19590101), ymd(19610101)),
                      interval(ymd(19800101), ymd(19820101)),
                      interval(ymd(19940101), ymd(19960101)),
                      interval(ymd(19490101), ymd(19510101))),
             result = c(NA, NA, NA, NA, 1, 2, NA, NA))

我需要找到标志为0的行中与标志为1的行的所有时间_1和时间_2变量有重叠的部分。

结果应该是一个列,它包含了第一个匹配的行号值,该值表示具有重叠的time_1和time_2间隔的标志为0的行与标志为1的行之间的匹配。为此,我尝试使用lubridate包中的int_overlap()函数。

借助map_int()函数,通过以下代码,我能够确定标志为0的一行与标志为1的任何行是否存在time_1重叠:

library(tidyverse)
library(lubridate)

df %>%
  group_by(id) %>%
  mutate(value = ifelse(flag == 0, map_int(time_1, ~ any(int_overlaps(.x, time_1[flag == 1]))), NA))

一个相关的问题可能会有所帮助:

R 查找时间段重叠

编辑:我想要获取一个列,用 row_number 变量标识第一个带有 time_1 和 time_2 重叠值的标志 1 行,该行与标志 0 行重叠。

id    flag  row_number         time_1                             time_2              result
1      1       1       2001-04-01 UTC--2001-05-01 UTC  1960-01-01 UTC--1962-01-01 UTC  NA

1      0       5       2001-04-17 UTC--2001-05-15 UTC  1959-01-01 UTC--1961-01-01 UTC  1

例如,满足条件的行号为1和5。结果是一个整数列,指示行号5(标志0行)的time_1和time_2与行号1(标志1)重叠。希望这样可以澄清问题。
2个回答

2

以下是使用 data.table 进行两次重叠连接的选项:

setkey(setDT(df), id, time_1_start, time_1_end)
ol1 <- foverlaps(df, df, nomatch=0L)[
    row_number!=i.row_number & i.flag==0L & flag==1L,
    .(id, irn=i.row_number, rn=row_number, flag=i.flag, 
        time_2_start=i.time_2_start, time_2_end=i.time_2_end)]

setkey(df, id, time_2_start, time_2_end)
setkey(ol1, id, time_2_start, time_2_end)
olaps <- foverlaps(ol1, df)[row_number!=irn & row_number==rn & i.flag==0L & flag==1L, 
    .(id, irn, xrn=row_number)]

df[olaps, on=.(id, row_number=irn), res := xrn]
setorder(df, row_number)
df

输出:

   id flag row_number time_1_start time_1_end time_2_start time_2_end res
1:  1    1          1   2001-04-01 2001-05-01   1960-01-01 1962-01-01  NA
2:  1    1          2   2007-08-01 2007-12-01   1980-01-01 1982-01-01  NA
3:  1    1          3   2010-03-01 2011-03-01   1949-01-01 1951-01-01  NA
4:  1    0          4   2001-04-15 2001-04-20   1981-01-01 1983-01-01  NA
5:  1    0          5   2001-04-17 2001-05-15   1959-01-01 1961-01-01   1
6:  1    0          6   2007-08-01 2007-12-01   1980-01-01 1982-01-01   2
7:  1    0          7   2011-01-01 2011-03-05   1994-01-01 1996-01-01  NA
8:  1    0          8   2017-12-01 2018-01-01   1949-01-01 1951-01-01  NA

数据:

library(data.table)
dtfun <- function(x) as.IDate(x, format="%Y%m%d")
df <- data.frame(id=c(1, 1, 1, 1, 1, 1, 1, 1),     
    flag=c(1, 1, 1, 0, 0, 0, 0, 0),
    row_number=c(1,2,3,4,5,6,7,8),
    time_1_start=dtfun(c("20010401","20070801","20100301","20010415",
        "20010417","20070801","20110101","20171201")),
    time_1_end=dtfun(c("20010501","20071201","20110301","20010420","
        20010515","20071201","20110305","20180101")),
    time_2_start=dtfun(c("19600101","19800101","19490101","19810101",
        "19590101","19800101","19940101","19490101")),
    time_2_end=dtfun(c("19620101","19820101","19510101","19830101",
        "19610101","19820101","19960101","19510101")))

0

我很确定我不完全理解你在寻找什么。在你的数据中,time_1和time_2相距很远,从未相交。这是正确的吗?

也许这会启动进展。这是你想要的吗?

df %>% 
  mutate(test = case_when(
    int_overlaps(time_1,time_2) & flag == 1 ~ T,
    int_overlaps(time_1,time_2) & flag == 0 ~ F,
    T ~ NA
    ))

我刚刚编辑了这篇文章,只是为了更清楚一点。谢谢。 - torakxkz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接