假设我有一个数据框,如:
set.seed(123)
df<-data.frame(id=rep(LETTERS[1:3],each=4),
days=as.integer(rnorm(12,100,10)),
event=rbinom(12,1,0.3))
df<-df[with(df,order(id,days)),]
df$event[sample(3,1:12,T)]<-NA
df[2,3]<-0
df
id days event
1 A 94 0
2 A 97 0
4 A 100 NA
3 A 115 0
8 B 87 1
5 B 101 0
7 B 104 1
6 B 117 0
9 C 93 0
10 C 95 1
12 C 103 0
11 C 112 0
如何通过忽略NAs来捕获days
到第一个event=1
,如果没有事件,则返回最大天数:
df2
id days event
3 A 115 0
8 B 87 1
10 C 95 1
答案 0 :(得分:4)
这被挤压成一行并使用data.table
:
require(data.table) ## >= 1.9.2
setDT(df)[, min(days[event==1], max(days), na.rm=TRUE), by=id]
它按照要求工作,但我仍然建议您将其拆分为两个(遇到事件,没有遇到事件)并合并表。当给定长度为0的向量时,这依赖于min()
返回Inf
。在这种情况下max(days)
开始。
setDT
通过引用将data.frame
转换为data.table
。
答案 1 :(得分:1)
对于这样的问题,通常最好将它们分成更小的块。首先,我们需要一个函数来为给定的id选择正确的事件。如下所示:
get_index = function(event) {
test = (event==1)
if(sum(test, na.rm=TRUE))
return(which.max(event))
else
return(max(which(!test)))
}
快速健全检查:
R> event = c(0, 0, NA, 0)
R> get_index(event)
[1] 4
R> event = c(0, 1, 0, 0)
R> get_index(event)
[1] 2
接下来,我们按ID分割数据并应用函数,所以
R> library(plyr)
R> ddply(df, .(id), summarize,
days = days[get_index(event)],
event=event[get_index(event)])
id days event
1 A 115 0
2 B 87 1
3 C 95 1
我们可以提高效率(我们两次调用get_index
),但这应该让你开始。