簡體   English   中英

R中匹配和計數字符串(DNA的k聚體)

[英]matching and counting strings (k-mer of DNA) in R

我有一個字符串列表(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 rows 16 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中實現嗎?

可能這有幫助

 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

如果您正在尋找速度,顯而易見的解決方案是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倍快 :)

我的回答沒有@bartektartanus那么快。 但是,它也很快,我寫了代碼......:D

與其他代碼相比,我的代碼的正面是:

  1. 不需要安裝未實現的stri_count_fixed版本
  2. 可能stringi包對於大型k-mers來說會變得很慢,因為它必須為模式生成所有可能的組合,然后檢查它們在數據中的存在並計算它出現的次數。
  3. 它也適用於長單個多個序列,具有相同的輸出非常快。
  4. 您可以為k設置值,而不是創建模式字符串。
  5. 如果您運行oligonucleotideFrequencyk在一個大的序列比12大,功能凍結過量內存使用和R重新啟動,同時與我的功能它運行非常快。

我的代碼

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 lapply下面的所有代碼並return(k_mers)它只返回所有k-的列表...使用相應的重復向量

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

我們最近發布了我們的'kebabs'包,作為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頻率矩陣。 默認情況下,矩陣是稀疏的(類'dgRMatrix'),但您也可以將結果強制為標准密集矩陣格式(但是,仍然省略任何序列中根本不存在的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和氨基酸序列也是如此。 然而,對於后者,k的限制明顯更低,因為對於相同的k,特征空間明顯更大。

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

我希望有所幫助。 如果您還有其他問題,請告訴我。

最好的問候,烏爾里希

另一種方法:

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 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM