根据列中连续值形成的模式从数据框中选择行

jer*_*ome 5 r dataframe dplyr

我的R水平一般,我想在以下操作上得到一些帮助。

假设我有以下数据框:

    >df
    ID   Label
    P1   M
    P1   S
    P2   M
    P2   M
    P2   S
    P3   M
    P3   S
    P3   M
    P4   S
    P4   M
    P5   M
    P5   M
    P5   S
Run Code Online (Sandbox Code Playgroud)

我希望能够选择相Label对于每个 ID 的变量的特定序列中出现的行。

对于一个模式"MS",预期输出是

    ID   Label
    P1   M
    P1   S
    P2   M
    P2   S
    P3   M
    P3   S
Run Code Online (Sandbox Code Playgroud)

对于一个模式"MMS",预期输出是

    ID   Label
    P2   M
    P2   M
    P2   S
    P5   M
    P5   M
    P5   S
Run Code Online (Sandbox Code Playgroud)

对于模式"SM",预期输出是:

    ID   Label
    P3   S
    P3   M
    P4   S
    P4   M
Run Code Online (Sandbox Code Playgroud)

请考虑这样一个事实:我正在处理的数据有很多行,并且我需要构建的解决方案需要适用于任意长度的模式。(例如“MSS”、“SM”、“MMSSMS”等)。我恳请您的帮助。

编辑:我已经更新了这个问题(示例数据帧和模式的输出示例"MMS"。我想补充一点,我希望在使用变量对数据进行分组后发生模式匹配ID,以便可以在按 分组的数据组中找到模式ID。抱歉第一次没说清楚。

最终编辑:@akrun、@boski 和 @tmfmnk 的答案对我有用。与 @tmfmnk 的解决方案(400k 行数据约 29 秒)相比,@boski 和 @akrun 的解决方案执行时间更快(400k 行数据约 2-10 秒)。我建议读者参考所有这三个解决方案。

bos*_*ski 1

您可以尝试使用gregexpr(). 首先粘贴所有标签并找到您要查找的图案的起始位置。

> df
   ID Label
1  P1     M
2  P1     S
3  P2     M
4  P2     M
5  P2     S
6  P3     M
7  P3     S
8  P3     S
9  P4     S
10 P4     M
11 P5     M
12 P5     M
13 P5     S
Run Code Online (Sandbox Code Playgroud)

编辑

我之前的解决方案没有检索整个模式(只是开始)。

pattern="SM"
starts=gregexpr(pattern=pattern,paste(df$Label,collapse=""))[[1]]
positions=as.vector(sapply(starts,function(x){ 
  s=seq(x,x+nchar(pattern)-1)
  if (all(df$ID[s]==df$ID[x])){
    return(s)
  } else {return(rep(NA,nchar(pattern)))}
  }))
positions=positions[which(!is.na(positions))]

df[positions,]
df[positions,]
   ID Label
1  P1     M
2  P1     S
4  P2     M
5  P2     S
6  P3     M
7  P3     S
12 P5     M
13 P5     S

pattern="MMS"
   ID Label
3  P2     M
4  P2     M
5  P2     S
11 P5     M
12 P5     M
13 P5     S

pattern="SM"
   ID Label
9  P4     S
10 P4     M
Run Code Online (Sandbox Code Playgroud)