python计算序列列表中是否存在子字符串的数量

python计算序列列表中是否存在子字符串的数量,python,string,numpy,scipy,bioinformatics,Python,String,Numpy,Scipy,Bioinformatics,你可以在这里得到数据! 底部下载 我正在用python分析生物数据 我写了一段代码,在长字符串列表中查找匹配的子字符串 子串在一个列表中,长度为7个核苷酸 因此在列表中,从AAAAAAA到TTTTTTT,共有16384个基序(子串),排列为A,C,G,T 这段代码有一个for循环,用于子字符串列表和嵌套在其中的长字符串列表 它工作正常,但由于列表有12000行,代码处理非常慢 换言之,提供AAAAA信息和下一个AAAAA C信息需要2分钟 因此,需要16384个图案才能通过12000行2分钟,这

你可以在这里得到数据! 底部下载

我正在用python分析生物数据

我写了一段代码,在长字符串列表中查找匹配的子字符串

子串在一个列表中,长度为7个核苷酸

因此在列表中,从AAAAAAA到TTTTTTT,共有16384个基序(子串),排列为A,C,G,T

这段代码有一个for循环,用于子字符串列表和嵌套在其中的长字符串列表

它工作正常,但由于列表有12000行,代码处理非常慢

换言之,提供AAAAA信息和下一个AAAAA C信息需要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的图案在整个序列列表中出现了多少次,而不是也出现了多少次!!!。所以,如果一个主题出现在一个字符串中,作为bool为真,那么增加一个值,然后增加一个值,然后增加一个值


不是字符串中的图案数量。

好问题。这是一个经典的计算机科学问题。是的,确实有一个更好的算法。您的处理每个长字符串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倍。

您的代码有一些奇怪的地方

  • 你所说的“排列”看起来更像笛卡尔积,可以使用
    itertools.product
    计算

  • 因为Python是零索引的,所以字符串的第一个元素在索引0处,因此类似于
    i[2].find(sMotif)<1
    的比较将返回
    True
    ,如果字符串正好在开头,这似乎有点奇怪

  • 您的
    OddsRatio、PValue
    Enrichment
    计算在循环内,但计数的归零和
    print
    都不在循环内,这意味着您在为每一新行累积计算它们,但不使用该信息进行任何操作

  • 在典型情况下,可以多次重新计算
    i[2]。查找(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
    
    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.sum(axis=0)
    [[1 4 1 3 2 5 4 3 3 2 3 2 3 2 3 1]]
    
    所以我估计整个问题大约需要20分钟,这对于这么少的代码来说并不坏。(我们可以通过做算术来加速
    motif\u-not\u-seen
    部分,但这只会让我们得到2倍的速度。)

    在更小的情况下,更容易看到输出:

    >>> 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})})
    
    >mot,nomot=count\u模体(列表,2)
    >>>莫特
    defaultdict(,
    {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}),
    对:计数器({'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})
    >>>诺莫
    defaultdict(,
    {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}),
    正确:计数器({'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})
    
    基本上,您的问题是序列比较。寻找序列中的基序是生物信息学中的一个基本问题。我想你可以搜索一些现有的算法或软件包。我在谷歌搜索了关键词“motif match”,这是我在第一页找到的: 一种干净且非常快速的方法(OP的数据约为15秒)是使用of,因为它在引擎盖下使用numpy,例如:

    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
    
    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.sum(axis=0)
    [[1 4 1 3 2 5 4 3 3 2 3 2 3 2 3 1]]
    
    现在,
    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']
    
    现在,您可以沿列求和、屏蔽非值或需要执行的任何操作,例如:

    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
    
    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.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的列表做了一个快速测试