需要帮助来加速这个功能

时间:2018-04-12 04:49:37

标签: python

输入:各种职位列表清单。

[['61097', '12204947'],
 ['61097', '239293'],
 ['61794', '37020977'],
 ['61794', '63243'],
 ['63243', '5380636']]

输出:一个排序列表,其中包含列表中唯一编号的数量。

[4, 3, 3, 3, 3]

这个想法很简单,我有一个列表列表,其中每个列表包含可变数量的位置(在我们的示例中,每个列表中只有2个,但最多存在10个列表)。我想循环遍历每个列表,如果存在任何包含相同编号的其他列表,则该列表将附加到原始列表。

示例:从上面获取输入数据并使用以下代码:

def gen_haplotype_blocks(df):
    counts = []
    for i in range(len(df)):
        my_list = [item for item in df if any(x in item for x in df[i])]
        my_list = list(itertools.chain.from_iterable(my_list))
        uniq_counts = len(set(my_list))
        counts.append(uniq_counts)
        clear_output()
        display('Currently Running ' +str(i))
    return sorted(counts, reverse=True)

我得到了预期的输出。在这种情况下,当我遍历第一个列表['61097', '12204947']时,我发现我的第二个列表['61097', '239293']都包含'61097',因此列出的列表会连接在一起并形成['61097', '12204947', '61097', '239293']。这是针对输出以下内容的每个列表完成的:

['61097', '12204947', '61097', '239293']
['61097', '12204947', '61097', '239293']
['61794', '37020977', '61794', '63243']
['61794', '37020977', '61794', '63243', '63243', '5380636']
['61794', '63243', '63243', '5380636']

完成此列表后,我会计算每个列表中唯一值的数量,将其附加到另一个列表,然后对最终列表进行排序并返回。

因此,在['61097', '12204947', '61097', '239293']的情况下,我们有两个'61097',一个'12204947'和一个'239293',相当于3个唯一数字。

虽然我的代码有效,但速度非常慢。跑了将近两个小时,仍然只能上线~44k。

我正在寻找一种方法来大大加快这个功能。优选地,不改变原始数据结构。我是python的新手。

提前致谢!

2 个答案:

答案 0 :(得分:2)

不确定您对“相当多”的期望是多少,但是从一开始就将内部list转换为set s会加快速度。以下工作在我的测试中大约快2.5倍:

def gen_haplotype_blocks_improved(df):
    df_set = [set(d) for d in df]
    counts = []
    for d1 in df_set:
        row = d1
        for d2 in df_set:
            if d1.intersection(d2) and d1 != d2:
                row = row.union(d2)
        counts.append(len(row))
    return sorted(counts, reverse=True)  

答案 1 :(得分:2)

太强相当提高程序的速度,尤其是对于较大的数据集。关键是使用哈希表或Python术语中的字典来存储不同的数字作为键,并且每个唯一数字的行作为值存在。然后在第二遍,根据字典合并每行的列表并计算唯一元素。

def gen_haplotype_blocks(input):
    unique_numbers = {}

    for i, numbers in enumerate(input):
        for number in numbers:
            if number in unique_numbers:
                unique_numbers[number].append(i)
            else:
                unique_numbers[number] = [i]

    output = [[] for _ in range(len(input))]

    for i, numbers in enumerate(input):
        for number in numbers:
            for line in unique_numbers[number]:
                output[i] += input[line]

    counts = [len(set(x)) for x in output]
    return sorted(counts, reverse=True)

理论上,算法的时间复杂度为O(N * N),N为输入列表的大小。因为您需要将每个列表与所有其他列表进行比较。但是在这种方法中,复杂度是O(N),对于更大的数据集而言应该更快。权衡是额外的空间复杂性。