Выявление перекрывающихся интервалов дат на сгруппированных данных - PullRequest
0 голосов
/ 11 ноября 2019

У меня есть большой набор данных, в котором я хочу идентифицировать наблюдения, которые перекрываются во времени и пространстве. Каждое наблюдение имеет уникальный идентификатор, и я уже определил те, которые перекрываются в пространстве, заданные overlap_space. Теперь я хочу проверить, совпадают ли начальные / конечные точки наблюдений, которые перекрываются в пространстве.

Ниже приведен простой пример:

start <- c("2007-06-27", "2010-06-30", "2015-01-01", "2012-01-01", "2010-01-01", "2009-01-01")
end <- c("2008-10-01", "2010-07-01", "2017-02-02", "2013-01-01", "2010-07-03", "2012-01-01")
df <- data.frame(id = c(1:6),
                 start = as.Date(start, format = "%Y-%m-%d"),
                 end = as.Date(end, format = "%Y-%m-%d"),
                 overlap_id = as.character(c("2, 4", "1, 3, 5", "2, 5", "1, 5, 6", "2, 3, 4", "4")))```

> df
  id      start        end overlap_id
1  1 2007-06-27 2008-10-01       2, 4
2  2 2010-06-30 2010-07-01    1, 3, 5
3  3 2015-01-01 2017-02-02       2, 5
4  4 2012-01-01 2013-01-01    1, 5, 6
5  5 2010-01-01 2010-07-03    2, 3, 4
6  6 2009-01-01 2012-01-01          4

Не все пространственно перекрывающиеся идентификаторы перекрываются во времени. Как мне определить те, которые делают? Другими словами, мне нужно сопоставить значение overlap_id (которое можно преобразовать в более длинный формат с tidyr::separate_rows(overlap_id), а также дату начала / окончания. Я пытался сделать интервалы дат, используя lubridate::interval, но я не сделалудалось убедиться, что перекрытия ограничены теми, которые указаны в overlap_id.

Это вывод, который я хотел бы:

> df
  id      start        end overlap_id  time_overlap overlap_dummy
1  1 2007-06-27 2008-10-01       2, 4           NA             0 
2  2 2010-06-30 2010-07-01    1, 3, 5            5             1
3  3 2015-01-01 2017-02-02       2, 5           NA             0
4  4 2012-01-01 2013-01-01    1, 5, 6            6             1
5  5 2010-01-01 2010-07-03    2, 3, 4            2             1
6  6 2009-01-01 2012-01-01          4            6             1

Любая помощь будет принята с благодарностью! Спасибо.

1 Ответ

2 голосов
/ 11 ноября 2019

Вот один из способов ...

library(lubridate)
library(tidyverse)

df2 <- df %>% separate_rows(overlap_id, convert = TRUE) %>%   #spread rows
  left_join(df %>% select(-overlap_id) %>%                    #add dates for overlap rows
                   rename(start1 = start,                     #avoid name clash on join
                          end1 = end),
            by = c("overlap_id" = "id")) %>% 
  filter(int_overlaps(interval(start, end),                   #delete non-overlapping
                      interval(start1, end1))) %>% 
  group_by(id) %>% 
  summarise(time_overlap = paste(overlap_id, sep = ", ")) %>% #paste overlaps if more than 1
  right_join(df)                                              #merge back to df (by id)

df2
# A tibble: 6 x 5
     id time_overlap start      end        overlap_id
  <int> <chr>        <date>     <date>     <fct>     
1     1 NA           2007-06-27 2008-10-01 2, 4      
2     2 5            2010-06-30 2010-07-01 1, 3, 5   
3     3 NA           2015-01-01 2017-02-02 2, 5      
4     4 6            2012-01-01 2013-01-01 1, 5, 6   
5     5 2            2010-01-01 2010-07-03 2, 3, 4   
6     6 4            2009-01-01 2012-01-01 4    
...