按用户汇总数据帧,在第一次发生处理之前保留每个用户的行

时间:2015-07-15 07:47:12

标签: r aggregate find-occurrences

在本网站的其他地方也存在类似的问题,但没有一个答案包含我需要做的所有事情。

我有一个数据框,我正在尝试改变时间。研究中的受试者可以从非治疗变为治疗,但不是另一种方式。受试者有多行治疗信息,我想找到第一次治疗,这很简单。问题是不是每个人都有治疗的发生,因此每当我运行我的算法以找到第一次出现这些人被删除。让我的问题更清楚:

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

1 个答案:

答案 0 :(得分:3)

我们可以用不同的方式做到这一点。 data.table的一个选项是在“ID”列分组的“处理”列上使用if/else条件。我们检查if治疗中没有值等于'1',然后返回Data.table(.SD)的子集,即(if(!any(treatment==1)) .SD)或else即如果“处理”中的“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

或者稍微更紧凑的方法是依赖“治疗”中当前值和先前值之间的差异,并检查差异是否大于或等于0.我们可以使用diff或{{1} }。在这种情况下,我得到治疗和治疗滞后之间的差异(默认情况下-给出'滞后'值。它是数据的devel版本中的一个新函数。)

shift

使用setDT(data)[, .SD[(treatment-shift(treatment, fill=0))>=0], by = ID] 的类似方法。我们根据'ID'然后根据'处理'中当前值和之前值之间的差异对dplyr行进行分组。

filter

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

中的ave
base R