一种选择是使用 dplyr 按“id”进行分组,然后计算“indc ==”D”的行的累积和。然后检查并过滤该累积和
require(dplyr)
df %>% group_by(id) %>% filter(cumsum(indc == "D") <= 1)
#Source: local data frame [14 x 5]
#Groups: id
#
# id time indc var1 var2
#1 1 1 C 1.5 1
#2 1 2 C 1.0 1
#3 1 3 D 7.0 1
#4 2 1 C 2.5 1
#5 2 2 C 3.5 1
#6 2 3 C 6.5 1
#7 2 4 D 3.0 1
#8 3 1 C 2.0 0
#9 3 2 C 7.5 0
#10 3 3 C 6.0 0
#11 3 4 C 8.0 0
#12 3 5 D 8.5 0
#13 4 1 C 4.0 0
#14 4 2 C 4.5 0
评论后编辑#1:
感谢@akrun 下面的评论,这里有两个关于如何子集化的更多选项:
选项 1:使用基 R:
df[with(df, ave(indc=='D', id, FUN=function(x) cumsum(x)<=1)),]
选项2:使用data.table:
require(data.table)
setDT(df)[,.SD[cumsum(indc=='D')<=1], by=id]
感谢@akrun
在OP评论后编辑#2:
例如,如果出现第一个“D”,然后在同一组中出现另一行,其中出现“C”(或其他字母),则并不 100% 清楚您希望如何删除行。如果它发生在第一个“D”出现之后,我最初的答案将保留这样的行。要更改该行为并删除第一个“D”出现后的所有行,您只需添加另一个cumsum
到代码中,如下所示(对于修改后的数据,如下所示):
df %>% group_by(id2) %>% filter(cumsum(cumsum(indc2 == "D")) <= 1L)
#Source: local data frame [13 x 5]
#Groups: id2
#
# id2 time2 indc2 var1 var2
#1 1 1 C 8.0 1
#2 1 2 C 5.0 1
#3 1 3 D 7.0 1
#4 2 1 C 1.0 1
#5 2 2 C 2.0 1
#6 2 3 D 9.0 1
#7 3 1 C 4.5 0
#8 3 2 C 3.0 0
#9 3 3 C 7.5 0
#10 3 4 C 1.5 0
#11 3 5 D 4.0 0
#12 4 1 C 6.0 0
#13 4 2 C 6.5 0
data
df <- structure(list(id2 = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L), .Label = c("1", "2",
"3", "4"), class = "factor"), time2 = c(1, 2, 3, 4, 1, 2, 3,
4, 5, 1, 2, 3, 4, 5, 6, 1, 2), indc2 = structure(c(1L, 1L, 2L,
1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L), .Label = c("C",
"D"), class = "factor"), var1 = c(8, 5, 7, 8.5, 1, 2, 9, 3.5,
2.5, 4.5, 3, 7.5, 1.5, 4, 5.5, 6, 6.5), var2 = c(1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("id2", "time2",
"indc2", "var1", "var2"), row.names = c(NA, -17L), class = "data.frame")
> df
id2 time2 indc2 var1 var2
1 1 1 C 8.0 1
2 1 2 C 5.0 1
3 1 3 D 7.0 1
4 1 4 C 8.5 1 <-- this row will also be removed now
5 2 1 C 1.0 1
6 2 2 C 2.0 1
7 2 3 D 9.0 1
8 2 4 D 3.5 1
9 2 5 D 2.5 0
10 3 1 C 4.5 0
11 3 2 C 3.0 0
12 3 3 C 7.5 0
13 3 4 C 1.5 0
14 3 5 D 4.0 0
15 3 6 D 5.5 0
16 4 1 C 6.0 0
17 4 2 C 6.5 0