根据多个正则表达式子字符串对变量进行排序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了根据多个正则表达式子字符串对变量进行排序相关的知识,希望对你有一定的参考价值。

我试图在R中订购一个变量,它是一个包含三个我想要订购的子串的文件名列表。文件名的格式如下:

MAF001.incMHC.zPGS.S1
MAF002.incMHC.zPGS.S1
MAF003.incMHC.zPGS.S1
MAF001.incMHC.zPGS.S2
MAF002.incMHC.zPGS.S2
MAF003.incMHC.zPGS.S2
MAF001.noMHC_incRS148.zPGS.S1
MAF002.noMHC_incRS148.zPGS.S1
MAF003.noMHC_incRS148.zPGS.S1
MAF001.noMHC_incRS148.zPGS.S2
MAF002.noMHC_incRS148.zPGS.S2
MAF003.noMHC_incRS148.zPGS.S2
MAF001.noMHC.zPGS.S1
MAF002.noMHC.zPGS.S1
MAF003.noMHC.zPGS.S1
MAF001.noMHC.zPGS.S2
MAF002.noMHC.zPGS.S2
MAF003.noMHC.zPGS.S2

我想首先在MAF子字符串,然后是MHC子字符串,然后是S子字符串上订购此列表,这样的顺序是:

MAF001.incMHC.zPGS.S1
MAF001.noMHC_incRS148.zPGS.S1
MAF001.noMHC.zPGS.S1
MAF001.incMHC.zPGS.S2
MAF001.noMHC_incRS148.zPGS.S2
MAF001.noMHC.zPGS.S2
MAF002.incMHC.zPGS.S1
MAF002.noMHC_incRS148.zPGS.S1
MAF002.noMHC.zPGS.S1
MAF002.incMHC.zPGS.S2
MAF002.noMHC_incRS148.zPGS.S2
MAF002.noMHC.zPGS.S2
MAF003.incMHC.zPGS.S1
MAF003.noMHC_incRS148.zPGS.S1
MAF003.noMHC.zPGS.S1
MAF003.incMHC.zPGS.S2
MAF003.noMHC_incRS148.zPGS.S2
MAF003.noMHC.zPGS.S2

在看到关于单个子串的这个问题的答案后,我已经玩过gsub:R Sort strings according to substring

但我不知道如何将这个想法扩展到字符串中的多个子串(混合字符和数字类)。

答案

这是基础R中的单行:

bar <- foo[order(sapply(strsplit(foo, "\\."), function(x) paste(x[1], x[4])))]
head(data.frame(result = bar), 10)

                          result
1          MAF001.incMHC.zPGS.S1
2  MAF001.noMHC_incRS148.zPGS.S1
3           MAF001.noMHC.zPGS.S1
4          MAF001.incMHC.zPGS.S2
5  MAF001.noMHC_incRS148.zPGS.S2
6           MAF001.noMHC.zPGS.S2
7          MAF002.incMHC.zPGS.S1
8  MAF002.noMHC_incRS148.zPGS.S1
9           MAF002.noMHC.zPGS.S1
10         MAF002.incMHC.zPGS.S2

说明:

  • .使用strsplit分割字符串:strsplit(foo, "\\.")
  • 提取并组合元素1和4:paste(x[1], x[4])
  • 使用order获取所有组合的顺序
  • foo[]获取相应的值

数据(foo):

c("MAF001.incMHC.zPGS.S1", "MAF002.incMHC.zPGS.S1", "MAF003.incMHC.zPGS.S1", 
"MAF001.incMHC.zPGS.S2", "MAF002.incMHC.zPGS.S2", "MAF003.incMHC.zPGS.S2", 
"MAF001.noMHC_incRS148.zPGS.S1", "MAF002.noMHC_incRS148.zPGS.S1", 
"MAF003.noMHC_incRS148.zPGS.S1", "MAF001.noMHC_incRS148.zPGS.S2", 
"MAF002.noMHC_incRS148.zPGS.S2", "MAF003.noMHC_incRS148.zPGS.S2", 
"MAF001.noMHC.zPGS.S1", "MAF002.noMHC.zPGS.S1", "MAF003.noMHC.zPGS.S1", 
"MAF001.noMHC.zPGS.S2", "MAF002.noMHC.zPGS.S2", "MAF003.noMHC.zPGS.S2"
)
另一答案

使用tidyrdplyr

library(tidyr)
library(dplyr)

df <- data.frame(filenames = c(...))

pattern = "^([^.]+)\\.([^.]+)"
df %>%
  extract(filenames, 
          into = c("maf", "mhc"), 
          regex = pattern, remove = FALSE) %>%
  arrange(maf, mhc) %>%
  select(filenames)

哪个收益率

                       filenames
1          MAF001.incMHC.zPGS.S1
2          MAF001.incMHC.zPGS.S2
3           MAF001.noMHC.zPGS.S1
4           MAF001.noMHC.zPGS.S2
5  MAF001.noMHC_incRS148.zPGS.S1
6  MAF001.noMHC_incRS148.zPGS.S2
7          MAF002.incMHC.zPGS.S1
8          MAF002.incMHC.zPGS.S2
9           MAF002.noMHC.zPGS.S1
10          MAF002.noMHC.zPGS.S2
11 MAF002.noMHC_incRS148.zPGS.S1
12 MAF002.noMHC_incRS148.zPGS.S2
13         MAF003.incMHC.zPGS.S1
14         MAF003.incMHC.zPGS.S2
15          MAF003.noMHC.zPGS.S1
16          MAF003.noMHC.zPGS.S2
17 MAF003.noMHC_incRS148.zPGS.S1
18 MAF003.noMHC_incRS148.zPGS.S2
另一答案

此结果与您想要的输出相匹配,但它只根据MAFS进行排序。我不明白如何使用MHC字符串进行排序,如果这个答案不能满足您的需求,请详细说明该部分。

library(stringr)
maf <- str_extract(filenames, "MAF\\d+\\.")
mhc <- str_extract(filenames, "\\..*MHC.*\\.")
s <- str_extract(filenames, "S\\d+$")

library(magrittr)
library(dplyr)

data.frame(filenames, maf, mhc, s) %>% 
  arrange(maf, s) %>% 
  select(filenames)

输出是:

                       filenames
1          MAF001.incMHC.zPGS.S1
2          MAF001.incMHC.zPGS.S2
3           MAF001.noMHC.zPGS.S1
4           MAF001.noMHC.zPGS.S2
5  MAF001.noMHC_incRS148.zPGS.S1
6  MAF001.noMHC_incRS148.zPGS.S2
7          MAF002.incMHC.zPGS.S1
8          MAF002.incMHC.zPGS.S2
9           MAF002.noMHC.zPGS.S1
10          MAF002.noMHC.zPGS.S2
11 MAF002.noMHC_incRS148.zPGS.S1
12 MAF002.noMHC_incRS148.zPGS.S2
13         MAF003.incMHC.zPGS.S1
14         MAF003.incMHC.zPGS.S2
15          MAF003.noMHC.zPGS.S1
16          MAF003.noMHC.zPGS.S2
17 MAF003.noMHC_incRS148.zPGS.S1
18 MAF003.noMHC_incRS148.zPGS.S2

filenames在哪里

filenames <- read.table(text="MAF001.incMHC.zPGS.S1
MAF002.incMHC.zPGS.S1
MAF003.incMHC.zPGS.S1
MAF001.incMHC.zPGS.S2
MAF002.incMHC.zPGS.S2
MAF003.incMHC.zPGS.S2
MAF001.noMHC_incRS148.zPGS.S1
MAF002.noMHC_incRS148.zPGS.S1
MAF003.noMHC_incRS148.zPGS.S1
MAF001.noMHC_incRS148.zPGS.S2
MAF002.noMHC_incRS148.zPGS.S2
MAF003.noMHC_incRS148.zPGS.S2
MAF001.noMHC.zPGS.S1
MAF002.noMHC.zPGS.S1
MAF003.noMHC.zPGS.S1
MAF001.noMHC.zPGS.S2
MAF002.noMHC.zPGS.S2
MAF003.noMHC.zPGS.S2", header=FALSE, stringsAsFactors=FALSE)
另一答案

这里已经添加了许多好的解决方案。我正在添加另一个仅基于vector的使用。

注意:OP打算对MAFMHCS子串进行排序。我坚持用这条规则对这三个人进行排序。因此,我的答案结果可能与其他答案不符。

该方法:

  1. 使用regmatches在OP中查找每个描述的子字符串
  2. 使用paste准备基于sort可以执行的字符串
  3. 使用setNames设置矢量名称
  4. 在名字上排序vectorv[order(names(setNames(v, paste(regmatches(v, regexpr("^MAF\\d+", v, perl = TRUE)), regmatches(v, regexpr("\\w*MHC\\w*", v, perl = TRUE)), regmatches(v, regexpr("\\w+\\d+$", v, perl = TRUE)) ))))] #Result [1] "MAF001.incMHC.zPGS.S1" [2] "MAF001.incMHC.zPGS.S2" [3] "MAF001.noMHC.zPGS.S1" [4] "MAF001.noMHC.zPGS.S2" [5] "MAF001.noMHC_incRS148.zPGS.S1" [6] "MAF001.noMHC_incRS148.zPGS.S2" [7] "MAF002.incMHC.zPGS.S1" [8] "MAF002.incMHC.zPGS.S2" [9] "MAF002.noMHC.zPGS.S1" [10] "MAF002.noMHC.zPGS.S2" [11] "MAF002.noMHC_incRS148.zPGS.S1" [12] "MAF002.noMHC_incRS148.zPGS.S2" [13] "MAF003.incMHC.zPGS.S1" [14] "MAF003.incMHC.zPGS.S2" [15] "MAF003.noMHC.zPGS.S1" [16] "MAF003.noMHC.zPGS.S2" [17] "MAF003.noMHC_incRS148.zPGS.S1" [18] "MAF003.noMHC_incRS148.zPGS.S2"

数据

v <- c("MAF001.incMHC.zPGS.S1", "MAF001.noMHC_incRS148.zPGS.S1", "MAF001.noMHC.zPGS.S1", 
       "MAF001.incMHC.zPGS.S2", "MAF001.noMHC_incRS148.zPGS.S2", "MAF001.noMHC.zPGS.S2", 
       "MAF002.incMHC.zPGS.S1", "MAF002.noMHC_incRS148.zPGS.S1", "MAF002.noMHC.zPGS.S1", 
       "MAF002.incMHC.zPGS.S2", "MAF002.noMHC_incRS148.zPGS.S2", "MAF002.noMHC.zPGS.S2", 
       "MAF003.incMHC.zPGS.S1", "MAF003.noMHC_incRS148.zPGS.S1", "MAF003.noMHC.zPGS.S1", 
       "MAF003.incMHC.zPGS.S2", "MAF003.noMHC_incRS148.zPGS.S2", "MAF003.noMHC.zPGS.S2"
)
另一答案

我有一个专门为这样的任务设计的功能:

功能

reg_sort <- function(x,...,verbose=F) {
    ellipsis <-   sapply(as.list(substitute(list(...)))[-1], deparse, simplify="array")
    reg_list <-   paste0(ellipsis, collapse=',')
    reg_list %<>% strsplit(",") %>% unlist %>% gsub("\\\\","\\",.,fixed=T)
    pattern  <-   reg_list %>% map_chr(~sub("^-\\\"","",.) %>% sub("\\\"$","",.) %>% sub("^\\\"","",.) %>% trimws)
    descInd  <-   reg_list %>% map_lgl(~grepl("^-\\\"",.)%>%as.logical)

    reg_extr <-   pattern %>% map(~str_extract(x,.)) %>% c(.,list(x)) %>% as.data.table
    reg_extr[] %<>% lapply(., function(x) type.convert(as.character(x), as.is = TRUE))

    map(rev(seq_along(pattern)),~{reg_extr<<-reg_extr[order(reg_extr[[.]],decreasing = descInd[.])]})

    if(verbose) { tmp<-lapply(reg_extr[,.SD,.SDcols=seq_along(pattern)],unique);names(tmp)<-pattern;tmp %>% print }

    return(reg_extr[[ncol(reg_extr)]])
}

数据:

vec <- c("MAF001.incMHC.zPGS.S1", "MAF002.incMHC.zPGS.S1", "MAF003.incMHC.zPGS.S1", 
  "MAF001.incMHC.zPGS.S2", "MAF002.incMHC.zPGS.S2", "MAF003.incMHC.zPGS.S2", 
  "MAF001.noMHC_incRS148.zPGS.S1", "MAF002.noMHC_incRS148.zPGS.S1", 
  "MAF003.noMHC_incRS148.zPGS.S1", "MAF001.noMHC_incRS148.zPGS.S2", 
  "MAF002.noMHC_incRS148.zPGS.S2", "MAF003.noMHC_incRS148.zPGS.S2", 
  "MAF001.noMHC.zPGS.S1", "MAF002.noMHC.zPGS.S1", "MAF003.noMHC.zPGS.S1", 
  "MAF001.noMHC.zPGS.S2", "MAF002.noMHC.zPGS.S2", "MAF003.noMHC.zPGS.S2"
)

呼叫:

reg_sort(x=vec, "^.*?(?=\\.)","(?<=\\.).*(?<=\\.S)","S\\d+$")

结果:(一个字符向量)

1          MAF001.incMHC.zPGS.S1
2          MAF001.incMHC.zPGS.S2
3           MAF001.noMHC.zPGS.S1
4           MAF001.noMHC.zPGS.S2
5  MAF001.noMHC_incRS148.zPGS.S1
6  MAF001.noMHC_incRS148.zPGS.S2
7          MAF002.incMHC.zPGS.S1
8          MAF002.incMHC.zPGS.S2
9           MAF002.noMHC.zPGS.S1
10      

以上是关于根据多个正则表达式子字符串对变量进行排序的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用正则表达式子进行否定匹配?

python正则表达式贪婪算法与非贪婪算法与正则表达式子模式的简单应用

正则表达式与回溯

Shell编程之正则表达式

正则表达式

shell 命令 之 sortuniqtrcuteval 与 正则表达式