R中匹配和计数字符串(DNA的k聚体)

时间:2014-10-28 04:07:22

标签: regex r string dna-sequence

我有一个字符串列表(DNA序列),包括A,T,C,G。我想找到所有的匹配并插入到表中,其列是这些DNA字母表的所有可能组合(4 ^ k;" k"是每个匹配的长度 - K-mer - 并且必须由用户指定)和行表示列表中的顺序匹配数。

让我们说我的名单包括5名成员:

DNAlst<-list("CAAACTGATTTT","GATGAAAGTAAAATACCG","ATTATGC","TGGA","CGCGCATCAA")

我想设置k=2(2-mer),因此可以使用4^2=16组合,包括AA,AT,AC,AG,TA,TT,...

所以我的表格会有5 rows16 columns。我想计算我的k-mers和列表成员之间的匹配数量。

我想要的结果:df:

lstMemb AA AT AC AG TA TT TC ...
  1     2  1  1  0  0  3  0
  2       ...
  3
  4
  5

你能帮我在R中实现吗?

5 个答案:

答案 0 :(得分:6)

可能有帮助

 source("http://bioconductor.org/biocLite.R")
 biocLite("Biostrings")
 library(Biostrings)
 t(sapply(DNAlst, function(x){x1 <-  DNAString(x)
                   oligonucleotideFrequency(x1,2)}))
  #     AA AC AG AT CA CC CG CT GA GC GG GT TA TC TG TT
  #[1,]  2  1  0  1  1  0  0  1  1  0  0  0  0  0  1  3
  #[2,]  5  1  1  2  0  1  1  0  2  0  0  1  2  0  1  0
  #[3,]  0  0  0  2  0  0  0  0  0  1  0  0  1  0  1  1
  #[4,]  0  0  0  0  0  0  0  0  1  0  1  0  0  0  1  0
  #[5,]  1  0  0  1  2  0  2  0  0  2  0  0  0  1  0  0

或者按照@Arun的建议,首先将list转换为vector

   oligonucleotideFrequency(DNAStringSet(unlist(DNAlst)), 2L)
   #     AA AC AG AT CA CC CG CT GA GC GG GT TA TC TG TT
   #[1,]  2  1  0  1  1  0  0  1  1  0  0  0  0  0  1  3
   #[2,]  5  1  1  2  0  1  1  0  2  0  0  1  2  0  1  0
   #[3,]  0  0  0  2  0  0  0  0  0  1  0  0  1  0  1  1
   #[4,]  0  0  0  0  0  0  0  0  1  0  1  0  0  0  1  0
   #[5,]  1  0  0  1  2  0  2  0  0  2  0  0  0  1  0  0

答案 1 :(得分:6)

如果您正在寻找速度,显而易见的解决方案是stringi包。 计数模式有stri_count_fixed函数。 现在,检查代码和基准!

DNAlst<-list("CAAACTGATTTT","GATGAAAGTAAAATACCG","ATTATGC","TGGA","CGCGCATCAA")
dna <- stri_paste(rep(c("A","C","G","T"),each=4),c("A","C","G","T"))
result <- t(sapply(DNAlst, stri_count_fixed,pattern=dna,overlap=TRUE))
colnames(result) <- dna
result
     AA AC AG AT CA CC CG CT GA GC GG GT TA TC TG TT
[1,]  2  1  0  1  1  0  0  1  1  0  0  0  0  0  1  3
[2,]  5  1  1  2  0  1  1  0  2  0  0  1  2  0  1  0
[3,]  0  0  0  2  0  0  0  0  0  1  0  0  1  0  1  1
[4,]  0  0  0  0  0  0  0  0  1  0  1  0  0  0  1  0
[5,]  1  0  0  1  2  0  2  0  0  2  0  0  0  1  0  0



fstri <- function(x){
    t(sapply(x, stri_count_fixed,dna,T))
}
fbio <- function(x){
    t(sapply(x, function(x){x1 <-  DNAString(x); oligonucleotideFrequency(x1,2)}))
}

all(fstri(DNAlst)==fbio(DNAlst)) #results are the same
[1] TRUE

longDNA <- sample(DNAlst,100,T)
microbenchmark(fstri(longDNA),fbio(longDNA))
Unit: microseconds
           expr        min         lq        mean     median         uq        max neval
 fstri(longDNA)    689.378    738.184    825.3014    766.862    793.134   6027.039   100
  fbio(longDNA) 118371.825 125552.401 129543.6585 127245.489 129165.711 359335.294   100
127245.489/766.862
## [1] 165.9301

加快了165倍:)

答案 2 :(得分:4)

我的回答并不像@bartektartanus那么快。但是,它也很快,我写了代码......:D

与其他代码相比,我的代码的正面是:

  1. 不需要安装未实现的stri_count_fixed
  2. 版本
  3. 对于大型k-mers来说,可能stringi包可能会变慢 必须为模式生成所有可能的组合,然后, 检查它们在数据中的存在并计算它出现的次数。
  4. 它也适用于长多个序列 相同的输出真的很快。
  5. 您可以为k添加值,而不是创建模式字符串。
  6. 如果您使用大于12的oligonucleotideFrequency运行k 在一个大的序列中,该函数冻结了过多的内存使用和 R重新启动,而我的功能运行得非常快。
  7. 我的代码

    sequence_kmers <- function(sequence, k){
        k_mers <- lapply(sequence,function(x){
            seq_loop_size <- length(DNAString(x))-k+1
    
            kmers <- sapply(1:seq_loop_size, function(z){
                y <- z + k -1
                kmer <- substr(x=x, start=z, stop=y)
                return(kmer)
            })
            return(kmers)
        })
    
        uniq <- unique(unlist(k_mers))
        ind <- t(sapply(k_mers, function(x){
            tabulate(match(x, uniq), length(uniq))
        }))
        colnames(ind) <- uniq
    
        return(ind)
    }
    

    我只使用Biostrings包计算基数......您可以使用stringi之类的其他选项来计算... 如果您删除k_mers lapplyreturn(k_mers)下面的所有代码,则只返回所有带有相应重复向量的k-me的列表

    sequence这里是一个1000bp

    的序列
    #same output for 1 or multiple sequences
    > sequence_kmers(sequence,4)[,1:10]
    GTCT TCTG CTGA TGAA GAAC AACG ACGC CGCG GCGA CGAG 
       4    4    3    4    4    8    6    4    5    5 
    > sequence_kmers(c(sequence,sequence),4)[,1:10]
         GTCT TCTG CTGA TGAA GAAC AACG ACGC CGCG GCGA CGAG
    [1,]    4    4    3    4    4    8    6    4    5    5
    [2,]    4    4    3    4    4    8    6    4    5    5
    

    使用我的功能完成测试:

    #super fast for 1 sequence
    > system.time({sequence_kmers(sequence,13)})
      usuário   sistema decorrido 
         0.08      0.00      0.08 
    
    #works fast for 1 sequence or 50 sequences of 1000bps
    > system.time({sequence_kmers(rep(sequence,50),4)})
         user    system   elapsed
         3.61      0.00      3.61 
    
    #same speed for 3-mers or 13-mers
    > system.time({sequence_kmers(rep(sequence,50),13)})
         user    system   elapsed
         3.63      0.00      3.62 
    

    使用Biostrings进行的测试:

    #Slow 1 sequence 12-mers
    > system.time({oligonucleotideFrequency(DNAString(sequence),12)})
         user    system   elapsed 
       150.11      1.14    151.37 
    
    #Biostrings package freezes for a single sequence of 13-mers
    > system.time({oligonucleotideFrequency(sequence,13)})  
    freezes, used all my 8gb RAM
    

答案 3 :(得分:4)

我们最近发布了我们的烤肉串&#39;包装作为Bioconductor的一部分 3.0发布。虽然这个包旨在提供序列内核 用于分类,回归和其他任务,例如基于相似性 集群,该软件包还包括有效计算k-mer频率的功能:

#installing kebabs:
#source("http://bioconductor.org/biocLite.R")
#biocLite(c("kebabs", "Biostrings"))
library(kebabs)

s1 <- DNAString("ATCGATCGATCGATCGATCGATCGACTGACTAGCTAGCTACGATCGACTG")
s1
s2 <- DNAString(paste0(rep(s1, 200), collate=""))
s2

sk13 <- spectrumKernel(k=13, normalized=FALSE)
system.time(kmerFreq <- drop(getExRep(s1, sk13)))
kmerFreq
system.time(kmerFreq <- drop(getExRep(s2, sk13)))
kmerFreq

所以你看到k-mer频率是作为显式获得的 k = 13的标准(非标准化)谱内核的特征向量。 此功能在高效的C ++代码中实现 一个前缀树,只考虑实际出现的k-mers 序列(如您所要求的)。你会看到即使是k = 13和一个序列 有数万个基数,计算只需要几分之一 一秒钟(我们5岁的戴尔服务器上19毫秒)。以上功能 也适用于DNAStringSets,但是,在这种情况下,你应该删除 drop()得到k-mer频率矩阵。矩阵是默认的 稀疏(类&#39; dgRMatrix&#39;),但您也可以强制执行结果 标准的密集矩阵格式(但是,仍然省略了没有的k-mers 在任何序列中都发生了):

sv <- c(DNAStringSet(s1), DNAStringSet(s2))
system.time(kmerFreq <- getExRep(sv, sk13))
kmerFreq
system.time(kmerFreq <- getExRep(sv, sk13, sparse=FALSE))
kmerFreq

k-mers可能有多长,可能取决于您的系统。在我们的系统上, 对于DNA序列,限制似乎是k = 22。对于RNA和RNA也是如此 氨基酸序列。然而,对于后者,k的限制 显着降低,因为特征空间显然很多 相同的k更大。

#for the kebabs documentation please see:
browseVignettes("kebabs")

我希望有所帮助。如果您有任何其他问题,请告诉我。

祝你好运, 乌尔里希

答案 4 :(得分:2)

另一种方法:

DNAlst<-list("CAAACTGATTTT","GATGAAAGTAAAATACCG","ATTATGC","TGGA","CGCGCATCAA","ACACACACACCA")
len <- 4
stri_sub_fun <- function(x) table(stri_sub(x,1:(stri_length(x)-len+1),length = len))
sapply(DNAlst, stri_sub_fun)
[[1]]

AAAC AACT ACTG ATTT CAAA CTGA GATT TGAT TTTT 
   1    1    1    1    1    1    1    1    1 

[[2]]

AAAA AAAG AAAT AAGT AATA ACCG AGTA ATAC ATGA GAAA GATG GTAA TAAA TACC TGAA 
   1    1    1    1    1    1    1    1    1    1    1    1    1    1    1 

[[3]]

ATGC ATTA TATG TTAT 
   1    1    1    1 

[[4]]

TGGA 
   1 

[[5]]

ATCA CATC CGCA CGCG GCAT GCGC TCAA 
   1    1    1    1    1    1    1 

[[6]]

ACAC ACCA CACA CACC 
   4    1    3    1