你可以在这里获取数据! 2shared底部下载
我正在用python分析生物数据。
我已经写下了一个代码,用于在长字符串列表列表中查找匹配的子字符串。
子串在列表中,长度为7个核苷酸。
所以在列表中,从AAAAAAA到TTTTTTT,存在16384个基序(子串),排列A,C,G,T。
这段代码有一个for循环用于子串列表和嵌套在里面的长字符串列表。
它工作正常,但由于列表列表包含12000行,代码处理速度非常慢。
换句话说,提供有关AAAAAAA的信息,以及下一个AAAAAAC的信息需要2分钟。
因此需要16384个图案才能通过12000行2分钟,需要(16384 * 2 == 32768分钟 - > 546小时 - > 22天......)
我正在使用scipy和numpy来获得Pvalues。
我想要的是计算序列表中存在和不存在子串的数量
长字符串列表和代码如下:
list_of_lists_long = [
[BGN, -0.054, AGGCAGCTGCAGCCACCGCGGGGCCTCAGTGGGGGTCTCTGG....]
[ABCB7, 0.109, GTCACATAAGACATTTTCTTTTTTTGTTGTTTTGGACTACAT....]
[GPR143, -0.137, AGGGGATGTGCTGGGGGTCCAGACCCCATATTCCTCAGACTC....]
[PLP2, -0.535, GCGAACTTCCCTCATTTCTCTCTGCAATCTGCAAATAACTCC....]
[VSIG4, 0.13, AAATGCCCCATTAGGCCAGGATCTGCTGACATAATTGCCTAG....]
[CCNB3, -0.071, CAGCAGCCACAGGGCTAAGCATGCATGTTAACAGGATCGGGA....]
[TCEAL3, 0.189, TGCCTTTGGCCTTCCATTCTGATTTCTCTGATGAGAATACGA....]
....] #12000 lines
是否有更快的逻辑来更快地处理代码?
我需要你的帮助!
提前谢谢。
=====================================
有没有更简单的方法,没有实施任何其他事情?
我认为模式匹配的迭代是问题......
我试图找到的是在整个序列列表中出现长度为7个主题的次数,而不是发生的事情!因此,如果一个主题存在于一个字符串中,它是一个TRUE为bool,那么增加一个值AND FALSE,然后增加另一个值。
不是字符串中的图案数量。
答案 0 :(得分:5)
很好的问题。这是一个典型的计算机科学问题。是的,确实有更好的算法。你的每个长字符串处理16384次。更好的方法是只处理每个长字符串一次。
不是在每个长字符串中搜索每个主题,而是应该记录每个长字符串中出现的主题。例如,如果您在以下字符串中搜索长度为2的图案:
s = 'ACGTAC'
然后你可以在长度为2的子串上运行一个循环并记录dict
中存在哪些子串:
motifAppearances = {}
for i in range(len(s)-1):
motif = s[i:i+2] # grab a length=2 substring
if motif not in motifAppearances:
motifAppearances[motif] = 0 # initialize the count
motifAppearances[motif] += 1 # increment the count
现在你已经完整地处理了整个字符串,并找到了它中存在的所有图案。在这种情况下,结果dict看起来像:
motifAppearances = {'AC':2, 'CG':1, 'GT':1, 'TA':1}
为您的案件做类似的事情应该将您的运行时间减少16384倍。
答案 1 :(得分:3)
干净且非常快速的方式(使用OP数据约15秒)将使用CountVectorizer的scikits-learn,因为它在引擎盖下使用numpy,例如:
from sklearn.feature_extraction.text import CountVectorizer
def make_chunks(s):
width = 2
return [s[i:i+width] for i in range(len(s)-width+1)]
l = ['ATTGCGGCTCACGAA', 'ACCTAGATACGACGG', 'CCCCTGTCCATGGTA']
vectorizer = CountVectorizer(tokenizer=make_chunks)
X = vectorizer.fit_transform(l)
现在X
是一个稀疏矩阵,其中所有可能的块都是列,序列是行,其中每个值都是每个序列中给定块的出现次数:
>>> X.toarray()
# aa ac ag at ca cc cg ...
[[1 1 0 1 1 0 2 1 1 2 1 0 0 1 1 1] # ATTGCGGCTCACGAA
[0 3 1 1 0 1 2 1 2 0 1 0 2 0 0 0] # ACCTAGATACGACGG
[0 0 0 1 1 4 0 1 0 0 1 2 1 1 2 0]] # CCCCTGTCCATGGTA
>>> (X.toarray()>0).astype(int) # the same but counting only once per sequence
[[1 1 0 1 1 0 1 1 1 1 1 0 0 1 1 1]
[0 1 1 1 0 1 1 1 1 0 1 0 1 0 0 0]
[0 0 0 1 1 1 0 1 0 0 1 1 1 1 1 0]]
>>> vectorizer.get_feature_names() # the columns(chunks)
[u'aa', u'ac', u'ag', u'at', u'ca', u'cc', u'cg', u'ct', u'ga', u'gc', u'gg', u'gt', u'ta', u'tc', u'tg', u'tt']
现在,您可以对列进行求和,屏蔽非值或您需要执行的任何操作,例如:
>>> X.sum(axis=0)
[[1 4 1 3 2 5 4 3 3 2 3 2 3 2 3 1]]
最后要查找给定主题出现的次数,必须找到相应主题/块的索引,然后在前一个总和中进行评估:
>>> index = vectorizer.vocabulary_.get('ag') # 'ag' is your motif
2 # this means third column
在您的情况下,您必须将列表分为两部分(正值和负值)以包含停机条件。我使用DSM的答案列表进行了快速测试,我的计算机运行大约需要3-4秒。如果我使用12 000长度4000序列,那么它需要不到一分钟。
编辑:可以找到使用OP数据的整个代码here。
答案 2 :(得分:2)
您的代码有几个奇怪的地方。
您所谓的“排列”看起来更像笛卡尔积,可以使用itertools.product
计算。
因为Python是零索引的,所以字符串的第一个元素位于索引0处,因此如果字符串在开头就在那里,那么像i[2].find(sMotif) < 1
这样的比较将返回True
,这似乎有点奇怪。
您的OddsRatio, PValue
和Enrichment
计算在循环内部,但计数归零和print
都没有,这意味着您要为每个计算累计计算它们新行,但没有对该信息做任何事情。
在典型案例中,您多次重新计算i[2].find(sMotif)
次。该结果未缓存。
假设我理解你想要计算的数字 - 而且我可能错了,因为有些事你正在做我不理解的事情 - 我会翻转逻辑。而不是循环遍历每个主题并尝试在每一行中计算它,循环遍历每一行并查看其中的内容。这大约是行数的7 *而不是图案的数量*行数。
例如:
import random
from itertools import product
from collections import defaultdict, Counter
N = 12000
datalength = 400
listoflists = [[str(i), random.uniform(-1, 1),
''.join([random.choice('AGCT') for c in range(datalength)])]
for i in range(N)]
def chunk(seq, width):
for i in range(len(seq)-width+1):
yield seq[i:i+width]
def count_motifs(datatriples, width=7):
motif_counts_by_down = defaultdict(Counter)
nonmotif_counts_by_down = defaultdict(Counter)
all_motifs = set(''.join(p) for p in product('AGCT',repeat=width))
for symbol, value, sdata in datatriples:
down = value < -0.5
# what did we see?
motifs_seen = set(chunk(sdata, width))
# what didn't we see?
motifs_not_seen = all_motifs - motifs_seen
# accumulate these
motif_counts_by_down[down].update(motifs_seen)
nonmotif_counts_by_down[down].update(motifs_not_seen)
return motif_counts_by_down, nonmotif_counts_by_down
(我降低线长只是为了让输出更快;如果线长10倍,代码需要10倍。)
这在我的慢速笔记本电脑上生成(插入一些换行符后):
>>> %time mot, nomot = count_motifs(listoflists, 7)
CPU times: user 1min 50s, sys: 60 ms, total: 1min 50s
Wall time: 1min 50s
所以我认为完整问题大约需要20分钟,这对于如此少的代码来说并不坏。 (我们可以通过算术来加速motifs_not_seen
部分,但这只会让我们得到两倍。)
在一个更小的案例中,更容易看到输出:
>>> mot, nomot = count_motifs(listoflists, 2)
>>> mot
defaultdict(<class 'collections.Counter'>,
{False: Counter({'CG': 61, 'TC': 58, 'AT': 55, 'GT': 54, 'CA': 53, 'GA': 53, 'AC': 52, 'CT': 51, 'CC': 50, 'AG': 49, 'TA': 48, 'GC': 47, 'GG': 45, 'TG': 45, 'AA': 43, 'TT': 40}),
True: Counter({'CT': 27, 'GT': 26, 'TC': 24, 'GC': 23, 'TA': 23, 'AC': 22, 'AG': 21, 'TG': 21, 'CC': 19, 'CG': 19, 'CA': 19, 'GG': 18, 'TT': 17, 'GA': 17, 'AA': 16, 'AT': 16})})
>>> nomot
defaultdict(<class 'collections.Counter'>,
{False: Counter({'TT': 31, 'AA': 28, 'GG': 26, 'TG': 26, 'GC': 24, 'TA': 23, 'AG': 22, 'CC': 21, 'CT': 20, 'AC': 19, 'GA': 18, 'CA': 18, 'GT': 17, 'AT': 16, 'TC': 13, 'CG': 10}),
True: Counter({'AA': 13, 'AT': 13, 'GA': 12, 'TT': 12, 'GG': 11, 'CC': 10, 'CA': 10, 'CG': 10, 'AG': 8, 'TG': 8, 'AC': 7, 'GC': 6, 'TA': 6, 'TC': 5, 'GT': 3, 'CT': 2})})
答案 3 :(得分:0)
基本上你的问题是序列比较。按顺序查找基序是Bioinfomatics中的一个基本问题。我想你可以搜索一些现有的算法或包。我在谷歌搜索关键词“motif match”,这是我在第一页中找到的: http://biowhat.ucsd.edu/homer/motif/ http://meme.nbcr.net/meme/doc/mast.html http://www.biomedcentral.com/1471-2105/8/189 http://www.benoslab.pitt.edu/stamp/
答案 4 :(得分:0)
我们写了一个名为Sylamer的工具。它计算相同给定长度的单词的出现次数。默认情况下,它会在排序基因的上下文中计算超几何测试,或者只输出计数。它可以对给定长度的所有可能单词执行此操作,但也可以指定较小的单词列表。它是用C语言编写的,并且非常适合快速处理。通过链接GNU科学库,我们可以非常快速地进行超几何计算。
答案 5 :(得分:-1)
我猜测问题是费希尔的确切测试。如果我在for循环之外计算P值,那么计算会变得更快。