R - 识别连续序列

R - identify consecutive sequences

我有一个包含 107635 行和 3 列的大文件:主题、感兴趣区域 (ROI) 和试验次数。 ROI 可以是 A、B、C、D、E、F。 我想要做的是只保留那些在 ROI 列中我有 B、C、D 的连续序列的试验,这是 B 第一次出现的时候。 B、C、D出现多少次都没有关系。

在下面的例子中,我可以保留ntrial 78和201,因为第一次出现B的后面是C和D。 但是,我需要去掉ntrial 10和400。在trial 10中B,C和D不连续。试玩400第一次出现B,B后面没有C和D

对于输出,我只需要在每一行中为要保留的试验保留一个值为 1 的列,并为要删除的试验对应的行设置一个值为 0 的列。

关于如何创建无需目视检查每次试验即可使程序自动化的代码的任何建议?

非常感谢!

subject ROI ntrial output
sbj05   A   78     1
sbj05   A   78     1
sbj05   A   78     1
sbj05   A   78     1
sbj05   A   78     1
sbj05   A   78     1
sbj05   B   78     1
sbj05   B   78     1
sbj05   C   78     1
sbj05   D   78     1
sbj05   E   78     1
sbj05   E   78     1
sbj05   E   78     1
sbj05   A   201    1
sbj05   A   201    1
sbj05   A   201    1
sbj05   A   201    1
sbj05   A   201    1
sbj05   B   201    1
sbj05   C   201    1
sbj05   D   201    1
sbj05   E   201    1
sbj05   E   201    1
sbj05   E   201    1
sbj05   F   201    1
sbj05   F   201    1
sbj05   A   10     0
sbj05   A   10     0
sbj05   A   10     0
sbj05   A   10     0
sbj05   B   10     0
sbj05   A   10     0
sbj05   C   10     0
sbj05   D   10     0
sbj05   E   10     0
sbj05   E   10     0
sbj05   A   400    0
sbj05   A   400    0
sbj05   A   400    0
sbj05   B   400    0
sbj05   A   400    0
sbj05   B   400    0
sbj05   C   400    0
sbj05   C   400    0
sbj05   C   400    0
sbj05   D   400    0
sbj05   E   400    0
sbj05   E   400    0
sbj05   D   400    0

这是使用 data.tablestringi

的尝试

首先,我定义了一些辅助函数,它将帮助我检测每组 B 的首次准确度,并验证它们后跟正确的序列

Myfunc <- function(x) {
               which(x == "B")[1L] == 
               stri_locate_first_regex(paste(x, collapse = ""), 'B*CD')[, 1L]
              } 

那么,实现就很简单了

library(data.table)
library(stringi)
setDT(df)[, if(Myfunc(ROI)) .SD, by = .(subject, ntrial)]
#     subject ntrial ROI
#  1:   sbj05     78   A
#  2:   sbj05     78   A
#  3:   sbj05     78   A
#  4:   sbj05     78   A
#  5:   sbj05     78   A
#  6:   sbj05     78   A
#  7:   sbj05     78   B
#  8:   sbj05     78   B
#  9:   sbj05     78   C
# 10:   sbj05     78   D
# 11:   sbj05     78   E
# 12:   sbj05     78   E
# 13:   sbj05     78   E
# 14:   sbj05    201   A
# 15:   sbj05    201   A
# 16:   sbj05    201   A
# 17:   sbj05    201   A
# 18:   sbj05    201   A
# 19:   sbj05    201   B
# 20:   sbj05    201   C
# 21:   sbj05    201   D
# 22:   sbj05    201   E
# 23:   sbj05    201   E
# 24:   sbj05    201   E
# 25:   sbj05    201   F
# 26:   sbj05    201   F

或者,如果您只想要一个额外的列,您可以

setDT(df)[, output := +Myfunc(ROI), by = .(subject, ntrial)]

这是另一个:

idx <- sapply(split(df, df$ntrial), function(x) { 
  B <- with(rle(x$ROI == "B"),  sum(lengths[seq(which.max(values))]))
  all(x$ROI[B:(B+2)] == c("B", "C", "D"))
})
subset(df, ntrial %in% names(which(idx)))

base Rmatchrle 的方式:

df$ output <- +as.logical(ave(as.character(df$ROI), df$ntrial, FUN=function(x) {rle(x[match("B",x):length(x)])$values[2] == "C"}))
#     subject ROI ntrial output
# 1    sbj05   A     78      1
# 2    sbj05   A     78      1
# 3    sbj05   A     78      1
# 4    sbj05   A     78      1
# 5    sbj05   A     78      1
# 6    sbj05   A     78      1
# 7    sbj05   B     78      1
# 8    sbj05   B     78      1
# 9    sbj05   C     78      1
# 10   sbj05   D     78      1
# 11   sbj05   E     78      1
# 12   sbj05   E     78      1
# 13   sbj05   E     78      1
# 14   sbj05   A    201      1
# 15   sbj05   A    201      1
# 16   sbj05   A    201      1
# 17   sbj05   A    201      1
# 18   sbj05   A    201      1
# 19   sbj05   B    201      1
# 20   sbj05   C    201      1
# 21   sbj05   D    201      1
# 22   sbj05   E    201      1
# 23   sbj05   E    201      1
# 24   sbj05   E    201      1
# 25   sbj05   F    201      1
# 26   sbj05   F    201      1
# 27   sbj05   A     10      0
# 28   sbj05   A     10      0
# 29   sbj05   A     10      0
# 30   sbj05   A     10      0
# 31   sbj05   B     10      0
# 32   sbj05   A     10      0
# 33   sbj05   C     10      0
# 34   sbj05   D     10      0
# 35   sbj05   E     10      0
# 36   sbj05   E     10      0
# 37   sbj05   A    400      0
# 38   sbj05   A    400      0
# 39   sbj05   A    400      0
# 40   sbj05   B    400      0
# 41   sbj05   A    400      0
# 42   sbj05   B    400      0
# 43   sbj05   C    400      0
# 44   sbj05   C    400      0
# 45   sbj05   C    400      0
# 46   sbj05   D    400      0
# 47   sbj05   E    400      0
# 48   sbj05   E    400      0
# 49   sbj05   D    400      0

未对齐的列让我很烦