基于一次出现的条件子集

Conditional subset based on one occurrence

我想将这样的数据库分为两部分:

df <- data.frame(ID = c(1,1,1,1,1,2,2,2,3,3,3), 
ins =c(1,2,3,4,5,3,2,4,5,8,9),
Ytx = c(NA,NA,1998,NA,NA,NA,NA,NA,NA,2011,NA))

ID ins  Ytx
  1   1   NA
  1   2   NA
  1   3 1998
  1   4   NA
  1   5   NA
  2   3   NA
  2   2   NA
  2   4   NA
  3   5   NA
  3   8 2011
  3   9   NA

第一个应该是这样的(出现 Ytx 之后的所有值按 ID 分组):

 ID ins  Ytx
  1   3 1998
  1   4   NA
  1   5   NA
  3   8 2011
  3   9   NA

还有一个是用剩下的东西做的:

ID ins  Ytx
  1   1   NA
  1   2   NA
  2   3   NA
  2   2   NA
  2   4   NA
  3   5   NA

感谢您的支持

在 base R 中,我们可以使用 avesplit。这会将数据分为两个列表。第一个是 Ytx 值之前的数据,第二个是 Ytx.

之后的行
split(df, with(df, ave(!is.na(Ytx), ID, FUN = cumsum)))
#Or if you may have multiple Ytx per ID
#split(df, with(df, ave(!is.na(Ytx), ID, FUN = cumsum)) > 0)

#$`0`
#  ID ins Ytx
#1  1   1  NA
#2  1   2  NA
#6  2   3  NA
#7  2   2  NA
#8  2   4  NA
#9  3   5  NA

#$`1`
#   ID ins  Ytx
#3   1   3 1998
#4   1   4   NA
#5   1   5   NA
#10  3   8 2011
#11  3   9   NA

这是一个使用 data.table 的选项:

setDT(df)[, rn := .I]
idx <- df[, 
    if (any(!is.na(Ytx))) 
        .I[seq(.N) >= match(TRUE, !is.na(Ytx))]
, ID]$V1

df[idx]:

   ID ins  Ytx rn
1:  1   3 1998  3
2:  1   4   NA  4
3:  1   5   NA  5
4:  3   8 2011 10
5:  3   9   NA 11

df[-idx]:

   ID ins Ytx rn
1:  1   1  NA  1
2:  1   2  NA  2
3:  2   3  NA  6
4:  2   2  NA  7
5:  2   4  NA  8
6:  3   5  NA  9

数据:

library(data.table)
df <- data.frame(ID = c(1,1,1,1,1,2,2,2,3,3,3), 
    ins =c(1,2,3,4,5,3,2,4,5,8,9),
    Ytx = c(NA,NA,1998,NA,NA,NA,NA,NA,NA,2011,NA))

另外两个 的备选方案:

# convert 'df' tot a 'data.table'
library(data.table)
setDT(df)

# alternative 1
split(df, df[, !!cumsum(!is.na(Ytx)), by = ID]$V1)

# alternative 2
split(df, df[, !!Reduce(`+`, !is.na(Ytx), accumulate = TRUE), by = ID]$V1)

两者都给出:

$`FALSE`
   ID ins Ytx
1:  1   1  NA
2:  1   2  NA
3:  2   3  NA
4:  2   2  NA
5:  2   4  NA
6:  3   5  NA

$`TRUE`
   ID ins  Ytx
1:  1   3 1998
2:  1   4   NA
3:  1   5   NA
4:  3   8 2011
5:  3   9   NA