R语言中使用单词边界过滤通路名称的问题排查
通路名称过滤问题及解决方法
问题背景
需要过滤通路名称,仅保留包含HEMATOPOIETIC、ERYTHROCYTE、ERYTHROID、STEM、STEMNESS、HEMATOPOIESIS的通路并绘制柱状图。原脚本因SYSTEM包含STEM,误匹配到REACTOME_NEURONAL_SYSTEM这类非目标通路;尝试给所有关键词加\b单词边界后无匹配结果,仅给STEM加\b能部分匹配,需解决该问题。
示例输入:
gsea_obese <- c( "RAMALHO_STEMNESS_UP", "IVANOVA_HEMATOPOIESIS_INTERMEDIATE_PROGENITOR", "BYSTRYKH_HEMATOPOIESIS_STEM_CELL_QTL_CIS", "IVANOVA_HEMATOPOIESIS_EARLY_PROGENITOR", "RIZ_ERYTHROID_DIFFERENTIATION", "BYSTRYKH_HEMATOPOIESIS_STEM_CELL_AND_BRAIN_QTL_CIS", "RIZ_ERYTHROID_DIFFERENTIATION_CCNE1", "REACTOME_CYTOKINE_SIGNALING_IN_IMMUNE_SYSTEM", "GOBP_ERYTHROCYTE_HOMEOSTASIS", "REACTOME_NEURONAL_SYSTEM", )
现有脚本:
obese <- gsea_obese %>% filter(FDR.q.val < 0.25) %>% filter(NOM.p.val < 0.05) %>% filter(str_detect(NAME, "HEMATOPOIETIC|ERYTHROCYTE|ERYTHROID|STEM|STEMNESS|HEMATOPOIESIS")) %>% arrange(FDR.q.val) ggplot(obese, aes(reorder(NAME, NES), NES)) + geom_col(aes(fill=FDR.q.val)) + scale_fill_gradient(low = "blue", high = "red") + coord_flip() + labs(x="Pathway", y="Normalized Enrichment Score", title="Enriched Genes JAK2 vs WT in Obese mice")
原因分析
- 单词边界
\b的局限性:正则中\b匹配的是「单词字符(字母、数字、下划线)」与「非单词字符」的边界,但通路名称用下划线_分隔,_属于单词字符,因此STEM前后的下划线无法触发\b边界。比如HEMATOPOIESIS_STEM_CELL里的STEM前后都是下划线,\bSTEM\b无法匹配;而单独给STEM加\b时,仅能匹配到字符串开头或结尾的STEM,无法覆盖所有场景。 - 原正则的宽泛匹配:原正则直接匹配关键词子串,导致
SYSTEM中的STEM被误匹配。
解决方法
方案1:匹配下划线或首尾包围的关键词
使用正则断言匹配「关键词在字符串开头/结尾,或被下划线包围」的场景,精准定位独立的关键词,避免误匹配。
修改后的过滤语句:
filter(str_detect(NAME, "(?:^|_)(HEMATOPOIETIC|ERYTHROCYTE|ERYTHROID|STEM|STEMNESS|HEMATOPOIESIS)(?:_|$)"))
正则解释:
(?:^|_):非捕获组,匹配字符串开头或下划线(关键词的前置边界)(HEMATOPOIETIC|ERYTHROCYTE|ERYTHROID|STEM|STEMNESS|HEMATOPOIESIS):目标关键词组(?:_|$):非捕获组,匹配下划线或字符串结尾(关键词的后置边界)
方案2:替换下划线后使用单词边界
先将通路名称中的下划线替换为空格(非单词字符),再用\b匹配独立关键词,适合习惯使用单词边界的场景:
filter(str_detect(str_replace_all(NAME, "_", " "), "\\b(HEMATOPOIETIC|ERYTHROCYTE|ERYTHROID|STEM|STEMNESS|HEMATOPOIESIS)\\b"))
完整修改后的脚本
# 模拟包含必要字段的数据框(实际使用时替换为你的真实数据) obese_df <- tibble( NAME = gsea_obese, FDR.q.val = runif(length(gsea_obese), 0, 0.3), NOM.p.val = runif(length(gsea_obese), 0, 0.1), NES = rnorm(length(gsea_obese)) ) obese <- obese_df %>% filter(FDR.q.val < 0.25) %>% filter(NOM.p.val < 0.05) %>% filter(str_detect(NAME, "(?:^|_)(HEMATOPOIETIC|ERYTHROCYTE|ERYTHROID|STEM|STEMNESS|HEMATOPOIESIS)(?:_|$)")) %>% arrange(FDR.q.val) ggplot(obese, aes(reorder(NAME, NES), NES)) + geom_col(aes(fill=FDR.q.val)) + scale_fill_gradient(low = "blue", high = "red") + coord_flip() + labs(x="通路名称", y="标准化富集分数", title="肥胖小鼠中JAK2 vs WT的富集基因")
内容的提问来源于stack exchange,提问作者daddabi
相关产品推荐
相关产品推荐

