[英]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
stri_count_fixed
版本 stringi
包對於大型k-mers來說會變得很慢,因為它必須為模式生成所有可能的組合,然后檢查它們在數據中的存在並計算它出現的次數。 k
設置值,而不是創建模式字符串。 oligonucleotideFrequency
與k
在一個大的序列比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.