我一直在摸不着头脑。我正在重新组织一些不平衡的面板数据(堆叠/长格式)。我需要将所有行保持到包括第一次出现的变量(indc = D)值的组(id),并保留尚未发生的组的行。我希望丢弃的唯一行是每组的行数,其中指标变量的值为第二个或更多(indc = D)。我还需要保留数据框中的所有列。
# Data
id<-factor(c(1,1,1,2,2,2,2,2, 3,3,3,3,3,3,4,4))
time<-c(1,2,3,1,2,3,4,5, 1,2,3,4,5,6, 1,2)
indc<-factor(c("C","C","D","C","C","C","D","D","C","C","C","C","D","D","C","C"))
var1<-sample(seq(1,8.5, by=0.5))
var2<-c(rep(1,8),rep(0,8))
df<-data.frame(id,time,indc,var1,var2)
我的尝试是使用by和match - 问题是它返回最后一个变量作为匹配和每个组的索引。我坚持如何达到最终的解决方案。
attempt<-by(df, df$id, function(x) {match(unique(x$indc=="D"), x$indc=="D")} )
results<-(do.call("rbind", attempt))
所需的结果是df2 df2<-df[c(1:3,4:7,9:13,15:16),]
如果有人对解决方案有任何想法,我将非常感激。
答案 0 :(得分:6)
一个选项是使用dplyr按“id”分组,然后计算“indc ==”D“的行的累积总和。然后检查并过滤此cumsum所在的行&lt; = 1。 / p>
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
感谢@ 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
例如,如果第一个“D”发生,然后在同一组中出现“C”(或其他字母)的另一行,则不清楚如何删除行。如果在第一次“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
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