[英]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.