输入:各种职位列表清单。
[['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的新手。
提前致谢!
答案 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),对于更大的数据集而言应该更快。权衡是额外的空间复杂性。