我的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 秒)。我建议读者参考所有这三个解决方案。
您可以尝试使用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)