首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >按用户聚合数据,在第一次处理之前为每个用户保留行

按用户聚合数据,在第一次处理之前为每个用户保留行
EN

Stack Overflow用户
提问于 2015-07-15 07:47:11
回答 1查看 69关注 0票数 2

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

我有一个数据,我试图将其转换为时变数据。研究对象可以从非治疗转变为治疗,但不能改变其他方式。受试者有多行治疗信息,我想找出治疗的第一次出现,这就够简单了。问题是,并不是每个人都有这种治疗,因此每当我运行我的算法来查找第一次出现的情况时,这些人就会被删除。为了使我的问题更清楚:

代码语言:javascript
运行
复制
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将被删除。

代码语言:javascript
运行
复制
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),]) 

是否有任何方法来扩展此代码,以使那些没有第一次出现的代码保持将每一行保持到第一次出现时为止?

总之,我希望我的数据如下所示:

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

回答已采纳

发布于 2015-07-15 07:50:38

我们可以用不同的方式来做。使用data.table的一个选项是对按“ID”列分组的“处理”列使用if/else条件。我们检查if中没有值等于'1',然后返回Data.table的子集(.SD),即(if(!any(treatment==1)) .SD)或else,即,如果'1‘值在’处理‘中,返回处理中第一个值的位置指数(等于1 (which(treatment==1)[1L]) ),得到序列(seq),并将该数值索引用于datatable子集。(.SD)

代码语言:javascript
运行
复制
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-。在这种情况下,我得到了处理和处理滞后之间的区别(默认情况下,shift给出“滞后”值。它是data.table开发版本中的一个新功能)

代码语言:javascript
运行
复制
setDT(data)[, .SD[(treatment-shift(treatment, fill=0))>=0], by = ID]

或者使用dplyr的类似方法。我们按“ID”进行分组,然后根据“处理”中当前值和以前值之间的差异对行进行filter

代码语言:javascript
运行
复制
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

或者是来自avebase R

代码语言:javascript
运行
复制
data[with(data, as.logical(ave(treatment, ID, 
                  FUN=function(x) c(0, diff(x))>=0))),]
票数 3
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31424406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档