Проверьте, находятся ли какие-либо даты в группе в пределах определенных временных интервалов для этой группы в - PullRequest
2 голосов
/ 22 апреля 2019

Я хотел бы создать новую переменную, которая указывает, находится ли date_date в каком-либо из диапазонов дат, перечисленных для идентификатора

. Я использовал этот код, чтобы получить построчное сравнение, но я хочуразверните это и сравните все строки идентификатора со всеми строками интервалов, перечисленных для этого идентификатора

df <- df %>%
  group_by(id) %>%
  mutate(between_any = ifelse((visit_date >= start & visit_date <= end), 1))

Я также пытался создать переменную интервала и использовать пересечение (visit_date, interval) перед изменением, однако я не смогполучить пересечение, чтобы работать для объекта даты.

Вот некоторые примеры данных:

df <- data.frame(id = c("a","a","a","a","a","b","b","b"),
                 visit_date = c("2001-08-22","2001-09-21","2001-10-30","2001-11-10","2001-12-20","2002-12-22", "2003-04-30","2003-05-10"),
                 start = c(NA,"2001-09-21",NA,"2001-11-10",NA,"2002-12-22", "2003-04-30",NA),
                 end = c(NA, "2001-11-01",NA,"2001-11-10",NA,"2002-12-22","2003-06-01",NA))

> df
id visit_date    start        end
a 2001-08-22       <NA>       <NA>
a 2001-09-21 2001-09-21 2001-11-01
a 2001-10-30       <NA>       <NA>
a 2001-11-10 2001-11-10 2001-11-10
a 2001-12-20       <NA>       <NA>
b 2002-12-22 2002-12-22 2002-12-22
b 2003-04-30 2003-04-30 2003-06-01
b 2003-05-10       <NA>       <NA>

Мой желаемый результат следующий:

id visit_date      start       end   between_any
a 2001-08-22       <NA>       <NA>      0
a 2001-09-21 2001-09-21 2001-11-01      1
a 2001-10-30       <NA>       <NA>      1
a 2001-11-10 2001-11-10 2001-11-10      1
a 2001-12-20       <NA>       <NA>      0
b 2002-12-22 2002-12-22 2002-12-22      1
b 2003-04-30 2003-04-30 2003-06-01      1
b 2003-05-10       <NA>       <NA>      1

Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 22 апреля 2019
Функция

in_range в пакете data.table делает именно это ...

library(data.table)

df <- df %>%
  group_by(id) %>%
  mutate(between_any = as.numeric((inrange(visit_date, start, end))))

#> df
#  id visit_date      start        end between_any
#1  a 2001-08-22       <NA>       <NA>           0
#2  a 2001-09-21 2001-09-21 2001-11-01           1
#3  a 2001-10-30       <NA>       <NA>           1
#4  a 2001-11-10 2001-11-10 2001-11-10           1
#5  a 2001-12-20       <NA>       <NA>           0
#6  b 2002-12-22 2002-12-22 2002-12-22           1
#7  b 2003-04-30 2003-04-30 2003-06-01           1
#8  b 2003-05-10       <NA>       <NA>           1

В форме data.table ...

dt <- setDT(df)      
dt[, between_any := inrange(visit_date, start, end), 
     by = id]
2 голосов
/ 22 апреля 2019

Мой ответ не такой "симпатичный", как хотелось бы, но он дает вам то, к чему вы стремитесь.

Сначала я конвертирую ваши даты в даты:

library(lubridate)
library(dplyr)
library(tibble)
library(tidyr)
library(purrr)

df <- data.frame(id = c("a","a","a","a","a","b","b","b"),
                 visit_date = c("2001-08-22","2001-09-21","2001-10-30","2001-11-10","2001-12-20","2002-12-22", "2003-04-30","2003-05-10"),
                 start = c(NA,"2001-09-21",NA,"2001-11-10",NA,"2002-12-22", "2003-04-30",NA),
                 end = c(NA, "2001-11-01",NA,"2001-11-10",NA,"2002-12-22","2003-06-01",NA)) %>%
  mutate_at(-1,as.Date)

> df
  id visit_date      start        end
1  a 2001-08-22       <NA>       <NA>
2  a 2001-09-21 2001-09-21 2001-11-01
3  a 2001-10-30       <NA>       <NA>
4  a 2001-11-10 2001-11-10 2001-11-10
5  a 2001-12-20       <NA>       <NA>
6  b 2002-12-22 2002-12-22 2002-12-22
7  b 2003-04-30 2003-04-30 2003-06-01
8  b 2003-05-10       <NA>       <NA>

Далее я создаю список интервалов для каждой группы:

df_intervals <- df %>% 
  mutate_at(-1,as.Date) %>%
  filter(!is.na(start),
         !is.na(end)) %>%
  mutate(interval = start %--% end) %>%
  select(id,interval) %>%
  group_by(id)

> df_intervals
# A tibble: 4 x 2
# Groups:   id [2]
  id    interval                      
  <fct> <S4: Interval>                
1 a     2001-09-21 UTC--2001-11-01 UTC
2 a     2001-11-10 UTC--2001-11-10 UTC
3 b     2002-12-22 UTC--2002-12-22 UTC
4 b     2003-04-30 UTC--2003-06-01 UTC

Наконец, я присоединяю данные интервалов к исходным данным на основе id и ищу visit_date внутри интервалов.

df_output <- df %>% as.tbl() %>%
  inner_join(df_intervals) %>%
  mutate(between_any = map2_lgl(visit_date,interval,~ .x >= int_start(.y) & .x <= int_end(.y))) %>%
  group_by(id,visit_date,start,end) %>%
  summarise(between_any = as.numeric(any(between_any)))

> df_output
# A tibble: 8 x 5
# Groups:   id, visit_date, start [8]
  id    visit_date start      end        between_any
  <fct> <date>     <date>     <date>           <dbl>
1 a     2001-08-22 NA         NA                   0
2 a     2001-09-21 2001-09-21 2001-11-01           1
3 a     2001-10-30 NA         NA                   1
4 a     2001-11-10 2001-11-10 2001-11-10           1
5 a     2001-12-20 NA         NA                   0
6 b     2002-12-22 2002-12-22 2002-12-22           1
7 b     2003-04-30 2003-04-30 2003-06-01           1
8 b     2003-05-10 NA         NA                   1
0 голосов
/ 22 апреля 2019

Другая возможность может быть:

df %>% 
 rowid_to_column() %>%
 full_join(df %>%
            filter(!is.na(start) & !is.na(end)) %>%
            mutate(interval = interval(ymd(start), ymd(end))) %>%
            select(id, interval), by = c("id" = "id")) %>%
 group_by(rowid, id) %>%
 summarise(between_any = max(ymd(visit_date) %within% interval * 1)) %>%
 left_join(df %>%
            rowid_to_column(), by = c("rowid" = "rowid",
                                      "id" = "id")) %>%
 ungroup() %>%
 select(-rowid)
  id    between_any visit_date start      end       
  <fct>       <dbl> <fct>      <fct>      <fct>     
1 a               0 2001-11-08 <NA>       <NA>      
2 a               1 2001-09-21 2001-09-21 2001-11-01
3 a               1 2001-10-30 <NA>       <NA>      
4 a               1 2001-11-10 2001-11-10 2001-11-10
5 a               0 2001-12-20 <NA>       <NA>      
6 b               1 2002-12-22 2002-12-22 2002-12-22
7 b               1 2003-04-30 2003-04-30 2003-06-01
8 b               1 2003-05-10 <NA>       <NA> 

Здесь сначала создается переменная интервала, а затем выполняется полное объединение на основе идентификатора. Во-вторых, он проверяет, находится ли «visit_date» в каких-либо интервалах для «id» и «rowid». Наконец, он объединяет результаты с исходными данными.

...