我搜索了SO,虽然有很多关于有条件删除行的QA但没有QA适合我的问题。
我有一个data.frame
包含变量x
,y
等的纵向测量值,在不同的时间点time
,在几个主题中id
。某些主题会遇到事件ev
(表示为1
,否则会0
表示time
。我想将最初的data.frame
缩减为:
这样,
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
答案 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)
以下是subset
和ave
的解决方案:
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