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