我有一个数据框,代表了数百名患者的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
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
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
Run Code Online (Sandbox Code Playgroud)
我需要弄清楚如何为每个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
Run Code Online (Sandbox Code Playgroud)
关于按日期在R中进行子集化的问题已经有几个问题,但它们通常涉及从特定日期或日期范围中对数据进行子集化,而不是按((变量结束日期) - (时间间隔))进行子集化.
为了完整起见,这里有两种data.table使用按组子集或非等值连接的方法。此外,lubridate用于确保即使在闰年的情况下也选择 12 个月的时间段。
这本质上是docendo discimus答案data.table的版本。然而,函数用于日期算术,因为如果过去的一年包含闰日,简单地减去 365 天将无法涵盖 OP 所要求的 12 个月的时间段:dplyrlubridate
library(data.table)
library(lubridate)
setDT(example.dat)[, .SD[Date >= max(Date) %m-% years(1)], by = ID]
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)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 版本(2016 年 11 月 25 日在 CRAN 上),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]]
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)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包含每个 12 个月期间的开始日期ID:
Run Code Online (Sandbox Code Playgroud)ID V1 1: 1 2004-06-14 2: 2 2008-07-20 3: 3 2005-05-18
非等值连接返回满足条件的行的索引
example.dat[mDT, on = .(ID, Date >= V1), which = TRUE]
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)[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))][]
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)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's%m-%将日期滚动到 2 月的最后一天,即 2015 年 2 月 28 日。这是一个基本解决方案。我们将ave日期作为数字进行操作,因为如果我们要使用原始"Date"值ave,则会尝试返回"Date"值。相反,ave返回 0/1 值并将!!它们转换为 FALSE/TRUE。
in_last_yr <- function(x) {
max_date <- as.Date(max(x), "1970-01-01")
x > seq(max_date, length = 2, by = "-1 year")[2]
}
subset(example.dat, !!ave(as.numeric(Date), ID, FUN = in_last_yr))
Run Code Online (Sandbox Code Playgroud)
更新 改进了确定去年的日期的方法。
| 归档时间: |
|
| 查看次数: |
1477 次 |
| 最近记录: |