有条件地从数据框中删除行(多个条件)

时间:2013-01-26 14:46:29

标签: r conditional dataframe

我搜索了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 个答案:

答案 0 :(得分: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

答案 1 :(得分:4)

以下是subsetave的解决方案:

subset(testdf, !ave(ev, id, FUN = cumsum))

答案 2 :(得分: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

答案 3 :(得分: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