R语言统计字符串多模式组合计数并创建新列的优化方案
问题描述
现有一个数据框,其中一列存储以下划线_分隔的长字符串,需要从该长字符串中统计仅由事件A、B构成的各类交替模式组合的出现次数,忽略其他无关字符。
待统计的模式既包含A_B、B_A这类两个事件的基础交替组合,也包含A、B连续交替重复n次形成的更长组合,需要统计每类组合在对应字符串中的总出现次数。
注意:非A/B的字符会作为连续AB序列的分隔符,不允许跨非A/B字符匹配模式,模式计数支持重叠匹配。
示例数据框
participant <- c("A", "B", "C") trial <- c(1,1,2) string_pattern <- c("A_B_A_C_A_B", "B_A_B_A_C_D_A_B", "A_B_C_A_B") df <- data.frame(participant, trial, string_pattern)
期望输出
participant trial string_pattern A_B B_A A_B_A B_A_B B_A_B_A 1 A 1 A_B_A_C_A_B 2 1 1 0 0 2 B 1 B_A_B_A_C_D_A_B 2 2 1 1 1 3 C 2 A_B_C_A_B 2 0 0 0 0
注:原提问中第一行A_B_A计数为2属于笔误,按匹配规则实际计数为1
原有实现的问题
之前逐模式手动编写计数规则的代码如下,随着待统计组合数量增加,手动枚举的方式效率极低,容易遗漏:
revised_df <- df%>% dplyr::mutate(A_B = stringr::str_count(string_pattern, "A_B"), B_A = stringr::str_count(string_pattern, "B_A"), B_A_B = string::str_count(string_pattern, "B_A_B"))
通用实现方案
通过自动生成所有目标长度的AB交替模式,批量完成计数,无需手动逐一枚举规则:
library(tidyverse) # 配置需要统计的模式最大长度(模式包含的A/B事件个数,示例最长为5个事件) max_pattern_len <- 5 # 自动生成所有AB交替模式 patterns <- map(2:max_pattern_len, function(k){ a_start <- paste0(rep(c("A","B"), length.out = k), collapse = "_") b_start <- paste0(rep(c("B","A"), length.out = k), collapse = "_") c(a_start, b_start) }) %>% unlist() # 定义模式计数函数 count_ab_patterns <- function(input_str, target_patterns) { # 提取所有被非AB字符分隔的连续AB交替片段 ab_segments <- str_extract_all(input_str, "(?:A_B)+(?:_A)?|(?:B_A)+(?:_B)?")[[1]] # 批量统计所有模式的出现次数 map_dfc(target_patterns, function(p){ # 用正向预查正则实现重叠匹配 match_regex <- paste0("(?=", p, ")") count_sum <- sum(str_count(ab_segments, match_regex)) tibble(!!p := count_sum) }) } # 应用到数据框,生成最终结果 revised_df <- df %>% mutate(map_dfr(string_pattern, count_ab_patterns, target_patterns = patterns))
方案说明
- 只需修改
max_pattern_len参数,即可自动生成所有长度从2到设定值的AB交替模式,无需手动编写每个模式的匹配规则 - 自动过滤非A/B字符的影响,仅在连续的AB交替片段内统计,不会跨无关字符匹配
- 采用正向预查正则实现重叠匹配,符合滑动窗口计数的需求
- 输出结果直接按列绑定到原数据框,和期望输出格式一致
内容的提问来源于stack exchange,提问作者Balachandar Kaliappan
相关产品推荐
相关产品推荐

