检查最接近1年的值

时间:2018-12-19 09:54:13

标签: r date dataframe dplyr

我在数据框中有很长的日期,列出了不同患者ID的日期。一位患者可以在列表中出现多次。像这样:

ID         dates
1          2016-01-10
1          2016-02-10
1          2017-01-10
1          2018-02-10
1          etc
2
2
2
2
3
3
3
3

我基本上想创建一个新列,为每位患者每1年标记一次:

ID         dates                 oneyear
1          2016-01-10               0
1          2016-02-10               NA
1          2017-01-10               1
1          2018-02-10               1
1          2018-02-11               NA
2 (new)    2012-02-03               0
2          2012-02-03               NA
2          2013-02-03               1
2
3
3
3
3

因此,我希望每个新患者都为0,同年不适用,新的一年或接近一年(可能是11个月)时为1。我将如何在R中执行此操作?

2 个答案:

答案 0 :(得分:0)

也许是这样?

一些数据(这是您发布时应具有的可复制示例):

library(tidyverse)
library(lubridate)

df2 <- df %>% 
  mutate(year = year(dates)) %>% #creates the year column (takes the year from dates)
  mutate(prev_year = lag(year)) %>%  #lag of the year column by one row
  mutate(lag_id = lag(id)) %>% #lag of id by one row
  mutate(one_year = if_else(lag_id != id, NA_real_, year - prev_year)) #calculates the diff in years

这是什么:

# A tibble: 10 x 6
      id dates       year prev_year lag_id one_year
   <dbl> <date>     <dbl>     <dbl>  <dbl>    <dbl>
 1     1 2017-01-01  2017        NA     NA       NA
 2     1 2017-01-02  2017      2017      1        0
 3     1 2018-02-02  2018      2017      1        1
 4     2 2017-01-01  2017      2018      1       NA
 5     2 2017-01-02  2017      2017      2        0
 6     2 2018-02-02  2018      2017      2        1
 7     3 2016-01-01  2016      2018      2       NA
 8     3 2017-01-02  2017      2016      3        1
 9     3 2017-02-02  2017      2017      3        0
10     3 2018-03-02  2018      2017      3        1

我想这就是你的追求。

答案 1 :(得分:0)

OP要求“ 检查接近1年的最接近值”,但是赞赏answer,该检查仅检查年份是否已更改。因此,目前尚不清楚OP是否要检查大约一年或只是一个新日期之间的日期差。

例如,在2012-12-31和2013-01-01之间,只有一天的差异,但年份已更改。另一方面,2013-01-01和2013-12-31位于同一日历年内,但相差将近一年。

因此,下面的解决方案针对年份的变化(与天数无关)返回newyear,对于日期差异大约返回oneyear。一年(与日历年无关)。

正如OP提到的11个月接近一年,我特意选择11/12 * 365 = 334.6天作为阈值。因此,任何大于此值的日期差都被视为大于“一年”。请调整此值以满足您的要求。

library(dplyr)
threshold_days <- 11/12*365
DF %>% 
  arrange(ID, dates) %>% # not required if data are already ordered
  group_by(ID) %>% 
  mutate(newyear = c(0, NA^(1 - diff(lubridate::year(dates)) >= 1)),
         oneyear = c(0, NA^(1 - (diff(dates, units = "days") > threshold_days))))
      ID dates      newyear oneyear
   <dbl> <date>       <dbl>   <dbl>
 1     1 2016-01-10       0       0
 2     1 2016-02-10      NA      NA
 3     1 2017-01-10       1       1
 4     1 2018-02-10       1       1
 5     1 2018-02-11      NA      NA
 6     2 2012-12-31       0       0
 7     2 2013-01-01       1      NA
 8     3 2013-01-01       0       0
 9     3 2013-12-31      NA       1
10     4 2013-12-31       0       0
11     4 2015-02-01       1       1
12     4 2015-02-02      NA      NA

请注意,用例newyear 2和3分别在oneyearID之间有所不同。用例ID 4证明如果间隔超过一年,则返回1

OP已请求返回NA来指示可以忽略的数据差异。为了在没有if_else()的情况下实现这一点,使用了幂运算。 NA^01,而NA^1(或任何其他指数)是NA

数据

DF <- readr::read_table(
"ID         dates
1          2016-01-10
1          2016-02-10
1          2017-01-10
1          2018-02-10
1          2018-02-11
2          2012-12-31
2          2013-01-01
3          2013-01-01
3          2013-12-31
4          2013-12-31
4          2015-02-01
4          2015-02-02")

附录

恕我直言,我发现OP的选择是用NA表示小的差距,并用ID标记0的第一次出现是有些人为的。在R中,01可以看作是逻辑值FALSETRUE的整数等效项,而NA通常表示缺失值。

因此,我的建议是对每个新患者(遗漏差异)使用NA,对同一年或少于一年的患者使用0,对新患者使用1或日期差大于一年。这将大大简化代码。

threshold_days <- 11/12*365
DF %>% 
  arrange(ID, dates) %>% # not required if data are already ordered
  group_by(ID) %>% 
  mutate(newyear = c(NA, diff(lubridate::year(dates)) >= 1),
         oneyear = c(NA, diff(dates, units = "days") > threshold_days))
      ID dates      newyear oneyear
   <dbl> <date>     <lgl>   <lgl>  
 1     1 2016-01-10 NA      NA     
 2     1 2016-02-10 FALSE   FALSE  
 3     1 2017-01-10 TRUE    TRUE   
 4     1 2018-02-10 TRUE    TRUE   
 5     1 2018-02-11 FALSE   FALSE  
 6     2 2012-12-31 NA      NA     
 7     2 2013-01-01 TRUE    FALSE  
 8     3 2013-01-01 NA      NA     
 9     3 2013-12-31 FALSE   TRUE   
10     4 2013-12-31 NA      NA     
11     4 2015-02-01 TRUE    TRUE   
12     4 2015-02-02 FALSE   FALSE