本网站其他地方也有与我类似的问题,但没有一个答案涵盖我需要做的所有事情。
我有一个数据框,我正在尝试将其更改为随时间变化的数据框。研究中的受试者可以从不治疗转为治疗,但不能从不治疗转为治疗。受试者有多行治疗信息,我想找到第一个出现的治疗,这很简单。问题在于,并不是每个人都会发生这种治疗,因此每当我运行算法来查找第一次发生时,这些人都会被删除。为了让我的问题更清楚:
ID treatment start.date stop.date
1 0 01/01/2002 01/02/2002
1 0 01/02/2002 01/03/2002
1 1 01/03/2002 01/04/2002
1 0 01/04/2002 01/05/2002
2 0 01/01/2002 01/02/2002
2 0 01/02/2002 01/03/2002
3 0 01/01/2002 01/02/2002
3 1 01/02/2002 01/03/2002
3 0 01/03/2002 01/04/2002
如您所见,2
从未接受过治疗。当我运行以下算法时,2
被删除。
data$keep <- with(data,
ave(treatment==1, ID ,FUN=function(x) if(1 %in% x) cumsum(x) else 2))
with(data, data[keep==0 | (treatment==1 & keep==1),])
有什么方法可以扩展此代码,以便它保留那些没有第一次出现的人并保持每一行直到第一次出现的人第一次出现吗?
总而言之,我希望我的数据如下所示:
ID treatment start.date stop.date
1 0 01/01/2002 01/02/2002
1 0 01/02/2002 01/03/2002
1 1 01/03/2002 01/04/2002
2 0 01/01/2002 01/02/2002
2 0 01/02/2002 01/03/2002
3 0 01/01/2002 01/02/2002
3 1 01/02/2002 01/03/2002
最佳答案
我们可以通过不同的方式做到这一点。 data.table
的一个选项是在按“ID”列分组的“treatment”列上使用 if/else
条件。我们检查if
处理中没有值等于“1”,然后返回 Data.table 的子集 (.SD
),即 (if( !any(treatment==1)) .SD
) 或 else
即,如果“treatment”中包含“1”值,则返回治疗中第一个值的位置索引,该索引等于1 (which(treatment==1)[1L]
),获取序列 (seq
) 并使用该数字索引对数据表进行子集化。 (.SD
)
library(data.table)#v1.9.5+
setDT(data)[, if(!any(treatment==1)) .SD
else .SD[seq(which(treatment==1)[1L])], by = ID]
# ID treatment start.date stop.date
#1: 1 0 01/01/2002 01/02/2002
#2: 1 0 01/02/2002 01/03/2002
#3: 1 1 01/03/2002 01/04/2002
#4: 2 0 01/01/2002 01/02/2002
#5: 2 0 01/02/2002 01/03/2002
#6: 3 0 01/01/2002 01/02/2002
#7: 3 1 01/02/2002 01/03/2002
或者一个稍微更紧凑的方法是依赖“treatment”中当前值和先前值之间的差异,并检查差异是否大于或等于 0。我们可以使用 diff
或 -
。在这种情况下,我得到了治疗和治疗滞后之间的差异(默认情况下shift
给出'lag'值。这是data.table的开发版本中的一个新函数)
setDT(data)[, .SD[(treatment-shift(treatment, fill=0))>=0], by = ID]
或者使用dplyr
的类似方法。我们按“ID”进行分组,然后根据“治疗”中当前值和先前值之间的差异过滤
行。
library(dplyr)
data %>%
group_by(ID) %>%
filter(c(0, diff(treatment)) >=0)
# ID treatment start.date stop.date
#1 1 0 01/01/2002 01/02/2002
#2 1 0 01/02/2002 01/03/2002
#3 1 1 01/03/2002 01/04/2002
#4 2 0 01/01/2002 01/02/2002
#5 2 0 01/02/2002 01/03/2002
#6 3 0 01/01/2002 01/02/2002
#7 3 1 01/02/2002 01/03/2002
或者使用来自base R
的ave
data[with(data, as.logical(ave(treatment, ID,
FUN=function(x) c(0, diff(x))>=0))),]
关于r - 按用户聚合数据帧,在第一次发生治疗之前保留每个用户的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31424406/