r - 按用户聚合数据帧,在第一次发生治疗之前保留每个用户的行

标签 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

最佳答案

我们可以通过不同的方式做到这一点。 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 Rave

data[with(data, as.logical(ave(treatment, ID, 
                  FUN=function(x) c(0, diff(x))>=0))),]

关于r - 按用户聚合数据帧,在第一次发生治疗之前保留每个用户的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31424406/

相关文章:

c# - python 是否具有与 C# 的 Enumerable.Aggregate 等效的功能?

group-by - 如何将函数应用于 GroupBy 对象的多个列?

node.js - 如何使用mongoDb获取字符串中关键字的出现次数

r - 逐行连接 data.table 中的列之间的值

regex - 使用 gsub 删除 R 中第一个空格之前的所有字符串

mysql - 聚合MySQL中两个表之间的数据

python - 从数据框中提取共现数据

java - 如何打印数组中出现的所有最大的两个整数?

R Markdown 找不到函数

r - 传播后如何保持订购