用于复杂变量拆分问题的正则表达式

时间:2018-11-29 22:02:13

标签: r regex strsplit

我有一个data.table变量,它们代表抗菌药物耐药性基因变异,对于每种药物类别,它们都被串联在一起。

我需要为每个基因变体分别生成一个二进制列,如果存在给定药物类别的基因变体,则标记为TRUE,否则为FALSE

新变量的名称应采用drugclass_genevariantname格式,其中drugclass是从原始变量的名称继承的,genevariantname是从使用strsplit的拆分操作中提取的值。

基因变体之间用分号;隔开,这是我在以下函数中用来分割的字符,它将返回data.table并在其上添加新的二进制列到最后:

getamr <- function(dt, amrcol, splitchar) {

    columnvector = dt[[amrcol]]

    if (all(is.na(columnvector))) {return(dt)}

    y = unique(unlist(strsplit(x = columnvector, split = splitchar)))

    y = sort(y)

    for (i in 1:length(y)) {

      dt[, noquote(paste0(amrcol, "_", y[i])) :=
           ifelse(grepl(y[i], columnvector, fixed = TRUE), TRUE, FALSE)]
    }

    return(dt)

  }

此功能可以很好地用于创建新列和识别每个基因变体是否存在。但是,由于格式复杂,无法正确地将基因变体的名称分配给新变量,例如:

  

gene1 [position1:oldAA-newAA; position2:oldAA-newAA]; gene2 [position1:oldAA-newAA]; gene3 [v]; gene4; gene5

在此示例中,我希望创建以下新变量:

  • drug1_gene1 [position1:oldAA-newAA]

  • drug1_gene1 [position2:oldAA-newAA]

  • drug1_gene2 [position1:oldAA-newAA]

  • drug1_gene3 [v]

  • drug1_gene4

  • drug1_gene5

我遇到的困难是在上面项目符号中的第一种和第二种情况下,其中原始字符串中的拆分字符位于方括号内。结果是:

  • drug1_gene1 [position1:oldAA-newAA

  • drug1_position2:oldAA-newAA]

...不再有意义,因为在第二种情况下,变体位置和变体已从发生它们的基因名称中孤立出来。

我应该如何修改上述函数以更正新的列名,以便:

  1. 在第一种情况下,方括号是封闭的
  2. 不同的位置和变化总是以基因名称开头

下面是一些示例数据,它们说明了此问题的复杂性:

# Load data.table:
library(data.table)

# Create example data:
mydt <- data.table(id = c(1,2,3,4,5), 
                 amr_drug1 = c("erm(B)[v];mdf(A)*;mph-(A)*;strA;sat2A", "mdf(A)*;strA;sat2A", "-", "erm(B)[v];mdf(A)*;mph-(A)*;strA;sat2A", "-"), 
                 amr_drug2 = c("-", "aph(6)-Id,strB[v]", "aph(6)-Id,strB[v]", "aph(6)-Id,strB[v]", "-"), 
                 amr_drug3 = c("gyrA_EC2[83:S-L]", "gyrA_EC2[83:S-L;87:D-N];parC_EC2[80:S-I]", "gyrA_EC2[83:S-L;87:D-N];parC_EC2[80:S-I]", "gyrA_EC2[83:S-L]", "-"), 
                 amr_drug4 = c("OXA-1", "OXA-1", "OXA-1", "OXA-1", "OXA-1"),
                 amr_drug5 = c("-", "-", "-", "-", "-"))


# Identify AMR columns:
amrcols <- grep("^amr", names(mydt), value = TRUE)

# Replace '-' with NA:
mydt[, c(amrcols) := lapply(.SD, function(x) ifelse(x == "-", NA_character_, x)), .SDcols = amrcols]

# Apply function across all AMR columns:
for (i in 1:length(amrcols)) { getamr(mydt, amrcols[i], ";") } 

第三amr列中的一个基因(gyrA_EC2)在方括号中包含两个变体-拆分操作后,第二个变体从基因名称中孤立出来-见下文:

> mydt
   id                             amr_drug1         amr_drug2                                amr_drug3 amr_drug4 amr_drug5
1:  1 erm(B)[v];mdf(A)*;mph-(A)*;strA;sat2A              <NA>                         gyrA_EC2[83:S-L]     OXA-1      <NA>
2:  2                    mdf(A)*;strA;sat2A aph(6)-Id,strB[v] gyrA_EC2[83:S-L;87:D-N];parC_EC2[80:S-I]     OXA-1      <NA>
3:  3                                  <NA> aph(6)-Id,strB[v] gyrA_EC2[83:S-L;87:D-N];parC_EC2[80:S-I]     OXA-1      <NA>
4:  4 erm(B)[v];mdf(A)*;mph-(A)*;strA;sat2A aph(6)-Id,strB[v]                         gyrA_EC2[83:S-L]     OXA-1      <NA>
5:  5                                  <NA>              <NA>                                     <NA>     OXA-1      <NA>
   amr_drug1_erm(B)[v] amr_drug1_mdf(A)* amr_drug1_mph-(A)* amr_drug1_sat2A amr_drug1_strA amr_drug2_aph(6)-Id,strB[v]
1:                TRUE              TRUE               TRUE            TRUE           TRUE                       FALSE
2:               FALSE              TRUE              FALSE            TRUE           TRUE                        TRUE
3:               FALSE             FALSE              FALSE           FALSE          FALSE                        TRUE
4:                TRUE              TRUE               TRUE            TRUE           TRUE                        TRUE
5:               FALSE             FALSE              FALSE           FALSE          FALSE                       FALSE
   amr_drug3_87:D-N] amr_drug3_gyrA_EC2[83:S-L amr_drug3_gyrA_EC2[83:S-L] amr_drug3_parC_EC2[80:S-I] amr_drug4_OXA-1
1:             FALSE                      TRUE                       TRUE                      FALSE            TRUE
2:              TRUE                      TRUE                      FALSE                       TRUE            TRUE
3:              TRUE                      TRUE                      FALSE                       TRUE            TRUE
4:             FALSE                      TRUE                       TRUE                      FALSE            TRUE
5:             FALSE                     FALSE                      FALSE                      FALSE            TRUE

任何能防止方括号内的第二个(或后续)变体与基因名称分离的解决方案,都将受到赞赏。

1 个答案:

答案 0 :(得分:1)

关于分割功能,您可以首先仅使用方括号在方括号之外的分号处使用以下模式进行分割:

;(?=(?:[^\[\]]*\[[^\[\]]*\])*[^\[\]]*$)

然后,在附加步骤中拆分内部具有分号的字符串,例如使用;|\[|\]作为拆分模式。保留第一结果以分解并重建嵌套值或类似值。

Regex demonstration