我的平均水平为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


我希望能够选择针对每个ID以变量Label的特定顺序出现的行。

对于模式"MS",预期输出为

    ID   Label
    P1   M
    P1   S
    P2   M
    P2   S
    P3   M
    P3   S


对于模式"MMS",预期输出为

    ID   Label
    P2   M
    P2   M
    P2   S
    P5   M
    P5   M
    P5   S


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

    ID   Label
    P3   S
    P3   M
    P4   S
    P4   M


请考虑以下事实:我正在处理的数据有很多行,而我需要构建的解决方案需要针对任意长度的模式工作。 (例如“ MSS”,“ SM”,“ MMSSMS”等)。我虚心请求您的协助。

编辑:我已经更新了这个问题(示例数据帧和模式"MMS"的输出示例。我想补充一点,我希望模式匹配在使用ID变量对数据进行分组之后进行,以便可以在由ID分组的多组数据。很抱歉,第一次无法清除。

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

最佳答案

您可以尝试使用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


编辑

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

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

10-04 13:55
查看更多