6

我已经搜索过 SO,尽管有很多关于有条件地删除行的 QA,但没有一个 QA 适合我的问题。

我有一个data.frame包含变量等的纵向测量值xy在不同的时间点time,在几个科目id中。一些受试者经历了一个事件ev(表示为1,否则0在一些time)。我想将初始值减少data.frame为:

  • 1)所有主题的行都没有经历过事件(好吧,这很容易)但也包括
  • 2)对于经历过事件的受试者,事件之前的所有行(即所有行的时间都小于那个人的事件时间)。

以便,

testdf<-data.frame(id=c(rep("A",4),rep("B",4),rep("C",4) ),
                   x=c(NA, NA, 1,2, 3, NA, NA, 1, 2, NA,NA, 5), 
                   y=rev(c(NA, NA, 1,2, 3, NA, NA, 1, 2, NA,NA, 5)),
                   time=c(1,2,3,4,0.1,0.5,10,20,3,2,1,0.5),
                   ev=c(0,0,0,0,0,1,0,0,0,0,0,1))

会减少到

   id  x  y time ev
1   A NA  5  1.0  0
2   A NA NA  2.0  0
3   A  1 NA  3.0  0
4   A  2  2  4.0  0
5   B  3  1  0.1  0
6   C  2  2  3.0  0
7   C NA  1  2.0  0
8   C NA NA  1.0  0
4

4 回答 4

4

基础解决方案:

> do.call(rbind, by(testdf, testdf$id, function(x) x[cumsum(x$ev) == 0,]))
     id  x  y time ev
A.1   A NA  5  1.0  0
A.2   A NA NA  2.0  0
A.3   A  1 NA  3.0  0
A.4   A  2  2  4.0  0
B     B  3  1  0.1  0
C.9   C  2  2  3.0  0
C.10  C NA  1  2.0  0
C.11  C NA NA  1.0  0
于 2013-01-26T15:09:27.663 回答
4

这是一个使用subsetand的解决方案ave

subset(testdf, !ave(ev, id, FUN = cumsum))
于 2013-01-26T15:16:34.560 回答
3

此解决方案data.table似乎适用于您的testdf. 这个想法是用来cumsum跟踪第一个事件开始后的位置。

require(data.table)
dt <- data.table(testdf, key=c("id"))
dt.out <- dt[, .SD[cumsum(ev) == 0], by=id]
> dt.out

#    id  x  y time ev
# 1:  A NA  5  1.0  0
# 2:  A NA NA  2.0  0
# 3:  A  1 NA  3.0  0
# 4:  A  2  2  4.0  0
# 5:  B  3  1  0.1  0
# 6:  C  2  2  3.0  0
# 7:  C NA  1  2.0  0
# 8:  C NA NA  1.0  0
于 2013-01-26T15:05:16.730 回答
3

这是一个例子:

> ddply(testdf, .(id), function(z) z[cumsum(z$ev) == 0, ])
  id  x  y time ev
1  A NA  5  1.0  0
2  A NA NA  2.0  0
3  A  1 NA  3.0  0
4  A  2  2  4.0  0
5  B  3  1  0.1  0
6  C  2  2  3.0  0
7  C NA  1  2.0  0
8  C NA NA  1.0  0
于 2013-01-26T15:07:50.783 回答