проверить, находится ли список дат в диапазоне дат в r - PullRequest
0 голосов
/ 05 мая 2018

Ниже приведены три основных столбца моих данных (squirrel_id = уникальный индивидуальный идентификатор, byear = год рождения и dyear = год смерти):

> summary(complete)
  squirrel_id        byear          dyear     
 Min.   :  416   Min.   :1989   Min.   :1989  
 1st Qu.: 4152   1st Qu.:1997   1st Qu.:1998  
 Median : 7870   Median :2003   Median :2004  
 Mean   :10419   Mean   :2004   Mean   :2004  
 3rd Qu.:16126   3rd Qu.:2011   3rd Qu.:2012  
 Max.   :23327   Max.   :2017   Max.   :2017 

У меня есть второй фрагмент данных (показанный ниже), который я пытаюсь включить в вышеупомянутый набор данных.

mast.yr<-c("1993", "1998", "2005", "2010", "2014")

Я пытаюсь сделать две вещи:

  1. Добавьте столбец, в котором указано, был ли человек (squirrel_id) жив в течение какого-либо из mast.yr лет (dyear - byear = диапазон лет жизни (включая byear и dyear).
  2. Добавьте еще один столбец, который подсчитывает, сколько mast.yr лет каждый человек (squirrel_id) пережил в течение жизни (dyear - byear = диапазон лет жизни (включая byear и dyear).

Чтобы сгенерировать первый столбец, я использовал функцию mutate в пакете dplyr, но я могу заставить его работать только для byear и dyear отдельно, например:

complete <- complete %>%
    mutate (mast = ifelse (byear %in% c("1993", "1998", "2005", "2010", "2014"), 1, 0), 
    mast = ifelse (dyear %in% c("1993", "1998", "2005", "2010", "2014"), 1, 0))) 

Но он не дает желаемого результата, поскольку рассматривает byear и dyear самостоятельно, а не как непрерывный период времени. Я попробовал решения, опубликованные здесь и здесь , но не повезло.

Любые предложения будут оценены!

Копию моих данных можно найти здесь . Для воспроизводимости в будущем, вот пример:

> head(DF)

> squirrel_id  byear dyear
  <dbl>        <int> <dbl>
  6715         2006  2006
  22274        2016  2017
  20445        2014  2017
  19528        2013  2013
  2674         1995  1995
  1419         1992  1993

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Хотя @Frank уже предоставил элегантное решение, но sqldf предоставляет более простые способы для неэквивалентных объединений. Использование sqldf решение может быть как:

mast.yr<-c("1993", "1998", "2005", "2010", "2014")

mastDf <- data.frame(year = as.integer(mast.yr))


library(sqldf)


sqldf("select dat.*, IFNULL(Mast.inMast,0) as n_Mast, IFNULL(Mast.inMast,0) >0 as inMast
       from dat left outer join 
      (select *, count(squirrel_id) as inMast 
      from dat, mastDf 
      where mastDf.year between dat.byear AND dat.dyear
      group by squirrel_id) Mast on
      dat.squirrel_id = Mast.squirrel_id")

#     squirrel_id byear dyear n_Mast inMast
# 1          6715  2006  2006      0      0
# 2         22274  2016  2017      0      0
# 3         20445  2014  2017      1      1
# 4         19528  2013  2013      0      0
# 5          2674  1995  1995      0      0
# 6          1419  1992  1992      0      0
# 7         15014  2004  2004      0      0
# 8         10946  2009  2012      1      1
# 9          4369  1998  1999      1      1
# 10         4344  1992  1999      2      1
#....90 more rows
0 голосов
/ 05 мая 2018
# put target years in a table
mastDF = data_frame(year = as.integer(mast.yr))

# count based on conditions    
dat %>% 
  mutate(in_mast = count_matches(., mastDF, year >= byear, year <= dyear) > 0) %>%
  as.tbl

# A tibble: 100 x 4
   squirrel_id byear dyear in_mast
         <int> <int> <int>   <lgl>
 1        6715  2006  2006   FALSE
 2       22274  2016  2017   FALSE
 3       20445  2014  2017    TRUE
 4       19528  2013  2013   FALSE
 5        2674  1995  1995   FALSE
 6        1419  1992  1992   FALSE
 7       15014  2004  2004   FALSE
 8       10946  2009  2012    TRUE
 9        4369  1998  1999    TRUE
10        4344  1992  1999    TRUE
# ... with 90 more rows

, где count_matches - вспомогательная функция:

library(data.table)
count_matches = function(DF, targetDF, ...){
  onexpr = substitute(list(...))
  data.table(targetDF)[data.table(DF), on=eval(onexpr), allow.cart=TRUE, .N, by=.EACHI]$N
}

Если вы хотите, чтобы количество и значение отличалось от нуля, это можно сделать, разбив его на последовательность mutate аргументов:

dat %>% 
  mutate(
    n_mast = count_matches(., mastDF, year >= byear, year <= dyear),
    in_mast = n_mast > 0
) %>% as.tbl

# A tibble: 6 x 5
  squirrel_id byear dyear n_mast in_mast
        <int> <int> <int>  <int>   <lgl>
1        6715  2006  2006      0   FALSE
2       22274  2016  2017      0   FALSE
3       20445  2014  2017      1    TRUE
4       19528  2013  2013      0   FALSE
5        2674  1995  1995      0   FALSE
6        1419  1992  1993      1    TRUE
...