我有一个数据框,代表了数百名患者的15年随访数据。我想创建数据框的子集,包括每位患者最近12个月的数据。
以下是我的数据的代表性示例(包括一个缺失值,因为我的实际数据集中缺少大量数据):
# Create example dataset.
example.dat <- data.frame(
ID = c(1,1,1,1,2,2,2,3,3,3), # patient ID numbers
Date = as.Date(c("2000-02-01", "2004-10-21", "2005-02-06", # follow-up dates
"2005-06-14", "2002-11-24", "2009-03-05",
"2009-07-20", "2005-09-02", "2006-01-15",
"2006-05-18")),
Cat = c("Yes", "Yes", "No", "Yes", "No", # responses to a categorical variable
"Yes", "Yes", NA, "No", "No")
)
example.dat
产生以下输出:
ID Date Cat
1 1 2000-02-01 Yes
2 1 2004-10-21 Yes
3 1 2005-02-06 No
4 1 2005-06-14 Yes
5 2 2002-11-24 No
6 2 2009-03-05 Yes
7 2 2009-07-20 Yes
8 3 2005-09-02 <NA>
9 3 2006-01-15 No
10 3 2006-05-18 No
我需要弄清楚如何为每个ID号分配最近的记录以及过去12个月的所有记录。
ID Date Cat
2 1 2004-10-21 Yes
3 1 2005-02-06 No
4 1 2005-06-14 Yes
6 2 2009-03-05 Yes
7 2 2009-07-20 Yes
8 3 2005-09-02 <NA>
9 3 2006-01-15 No
10 3 2006-05-18 No
关于按日期在R中进行子集化的问题已经提出了几个问题,但它们通常关注的是从特定日期或日期范围中对数据进行子集化,而不是按((变量结束日期) - (时间间隔))进行子集化。 / p>
答案 0 :(得分:4)
为了完整起见,这里有两种data.table
方法,使用按组子集或非等连接。此外,lubridate
用于确保即使在闰年的情况下也会选择12个月的时间。
这绝对是docendo discimus' dplyr
answer的data.table
版本。但是,lubridate
函数用于日期算术,因为如果过去的一年包含闰日,简单地减去365天将不会覆盖OP请求的12个月期间:
library(data.table)
library(lubridate)
setDT(example.dat)[, .SD[Date >= max(Date) %m-% years(1)], by = ID]
ID Date Cat 1: 1 2004-10-21 Yes 2: 1 2005-02-06 No 3: 1 2005-06-14 Yes 4: 2 2009-03-05 Yes 5: 2 2009-07-20 Yes 6: 3 2005-09-02 NA 7: 3 2006-01-15 No 8: 3 2006-05-18 No
使用版本v1.9.8 (on CRAN 25 Nov 2016),data.table
已获得执行非等联接的功能:
library(data.table)
library(lubridate)
mDT <- setDT(example.dat)[, max(Date) %m-% years(1), by = ID]
example.dat[example.dat[mDT, on = .(ID, Date >= V1), which = TRUE]]
ID Date Cat 1: 1 2004-10-21 Yes 2: 1 2005-02-06 No 3: 1 2005-06-14 Yes 4: 2 2009-03-05 Yes 5: 2 2009-07-20 Yes 6: 3 2005-09-02 NA 7: 3 2006-01-15 No 8: 3 2006-05-18 No
mDT
包含每个ID
的12个月期间的开始日期:
ID V1 1: 1 2004-06-14 2: 2 2008-07-20 3: 3 2005-05-18
非equi连接返回满足条件的行的索引
example.dat[mDT, on = .(ID, Date >= V1), which = TRUE]
[1] 2 3 4 6 7 8 9 10
然后用于最终子集example.dat
。
到目前为止发布的答案采用了三种不同的方法来查找12个月前的日期:
seq.Date()
,years()
和%m-%
如果在此期间包含闰日,这三种方法会有所不同:
library(data.table)
library(lubridate)
mseq <- Vectorize(function(x) seq(x, length = 2L, by = "-1 year")[2L])
data.table(Date = as.Date("2016-02-28") + 0:2)[
, minus_365d := Date -365][
, minus_1yr := Date - years()][
, minus_1yr_m := Date %m-% years()][
, seq.Date := as_date(mseq(Date))][]
Date minus_365d minus_1yr minus_1yr_m seq.Date 1: 2016-02-28 2015-02-28 2015-02-28 2015-02-28 2015-02-28 2: 2016-02-29 2015-03-01 <NA> 2015-02-28 2015-03-01 3: 2016-03-01 2015-03-02 2015-03-01 2015-03-01 2015-03-01
no
个闰日,则所有三种方法都会返回相同的结果(第1行)。 seq.Date()
方法会选择2015年3月1日的第二天,因为2015年2月29日没有。使用lubridate
'%m-%
将日期推迟到2015年2月28日的最后一天,而不是。答案 1 :(得分:3)
这是一个基本解决方案。我们{9}以日期作为数字进行操作,因为如果我们使用原始ave
值"Date"
,则会尝试返回ave
值。相反,"Date"
返回0/1值,ave
将这些值转换为FALSE / TRUE。
!!
更新确定去年哪些天数的改进方法。
答案 2 :(得分:2)
使用dplyr
library(dplyr)
example.dat %>% group_by(ID) %>% filter(Date >= max(Date)-365)
#Source: local data frame [8 x 3]
#Groups: ID
#
# ID Date Cat
#1 1 2004-10-21 Yes
#2 1 2005-02-06 No
#3 1 2005-06-14 Yes
#4 2 2009-03-05 Yes
#5 2 2009-07-20 Yes
#6 3 2005-09-02 NA
#7 3 2006-01-15 No
#8 3 2006-05-18 No